OmniAICreator/Qiita-1.07M huggingface dataset:
Object trackingの評価データと評価指標についてまとめてみた

## 経緯
最近、object trackingに触れる機会があったのですが、評価データや評価方法について気になったので調べてみました。

## short-termとlong-termについて
object detectionは、short-termとlong-termで手法が分かれています。short-termは短時間で、フレームから対象物が消えたりはしないシチュエーションです。long-termはt長時間で、**フレームから対象物が消えたります。**現在は、実世界のシチュエーションにより近い**long-termの研究が盛んになっています。**そこで今回はlong-termの評価について調査した結果をまとめました。フレーム数は約15万。

## 主な評価データ
多くの論文で用いられているデータセットは下の２つでした。
### 1. [VOT2018-LT](https://www.votchallenge.net/vot2018/index.html)
visual object tracking 2018 long termの略です。2013年ぐらいから毎年Object trackin用のデータセットが提供されています。人や車、自転車、動物など様々な物体が対象です。RGB画像(30fpsが多い)とbounding boxが提供されています。人と乗り物多めです。LTとつくものはlong term用のデータセットで、targetが一度フレームから消えたりするデータがあります。
![car8.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663246/786bacf6-65be-9c09-06c7-a27525175a5c.gif)

### 2. [LaSOT](http://vision.cs.stonybrook.edu/~lasot/)
最近作成されたデータセット。400万枚近いフレーム数と80以上のクラス数が特徴。
![Screenshot from 2020-11-22 16-18-10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663246/76b560c2-5100-7df1-df12-c283faab927f.png)

## 評価指標
VOTの評価指標はPrecision、Recall、F-scoreが用いられています。詳しくは[こちら](https://openaccess.thecvf.com/content_ECCVW_2018/papers/11129/Kristan_The_sixth_Visual_Object_Tracking_VOT2018_challenge_results_ECCVW_2018_paper.pdf)に書いてあります。Precisionは以下の式で求められています。Ω(At(τθ), Gt)がフレームごとのprediction(At)とground truth(Gt)とのIoUです。τθはしきい値で、主に0.5が使われています。θtは確信度です。なのでしきい値以下の確信度の場合、At(θt)は0になります。Npは、物体があると推論されたフレームの数です。
![Screenshot from 2020-11-22 16-23-26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663246/c83ae117-3b75-4a18-48b6-4f679ffd9a8d.png)

RecallはPrecisionとほとんど同じですが、Npの代わりにNgを用いています。Ngは物体がフレームの中にあるデータの数です。
![Screenshot from 2020-11-22 16-23-52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663246/94261169-8bd9-1890-7091-9abed973a23e.png)

上の式で求めたPrとReを使って、F-scoreを算出します。
![Screenshot from 2020-11-22 16-24-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663246/5274d8e6-2d98-bff8-6a27-6099fc93864a.png)

## まとめ
Object trackingは、今結構盛り上がっている分野のようです。物体検出自体の精度が天井に近づきつつあるからからもしれません。あと、中国の研究者の論文が多いなと感じました。社会の様々なところで使われているからかもしれませんね(笑)。

**間違いや質問、ご意見等ありましたらお気軽にコメントください。頑張って答えますので(笑)。**
Jestのインストール〜実行の流れ

#Jestインストール〜実行まで


####①Jestをインストール

```
npm install --save-dev jest
```

####②基本設定ファイルの作成
1.node_modules/.binに対してinitで作成。

```
./node_modules/.bin/jest --init
```

2.基本的にEnter連打でok

```
The following questions will help Jest to create a suitable configuration for your project

✔ Would you like to use Jest when running "test" script in "package.json"? … yes
✔ Would you like to use Typescript for the configuration file? … no
✔ Choose the test environment that will be used for testing › node
✔ Do you want Jest to add coverage reports? … no
✔ Which provider should be used to instrument code for coverage? › v8
✔ Automatically clear mock calls and instances between every test? … no

✏️  Modified /Users/masahiro/Documents/react-router-test/project/package.json

📝  Configuration file created at /Users/masahiro/Documents/react-router-test/project/jest.config.js
```
####③babelのインストール
1.import,exportをテスト環境で使用する場合、babelのインストールが必要。
下記コマンドでインストールする

```
npm install --save-dev babel-jest @babel/core @babel/preset-env
```
2.{}package.jsonの"devDependencies"に下記が追加されていればok


```
 "devDependencies": {
    "@babel/core": "^7.12.7",
    "@babel/preset-env": "^7.12.7",
    "babel-jest": "^26.6.3",
    "jest": "^26.6.3"
  }
}
```
####④基本ファイルの作成
1.babel.config.jsファイルを作成し、下記のコードを追加

```
module.exports = {
  presets: [['@babel/preset-env', {targets: {node: 'current'}}]],
};
```

####⑤testフォルダの作成

1.`__test__`フォルダの作成し、適当なコードを入力

```
import QuizFetcher from '../../../src/data_fetchers/QuizFetcher';

describe('QuizFetcherのテスト', () => {
  it('クラスチェック', () => {
    console.log('@@@@@@');
  });
});
```
####⑥テスト実行
1.npm testを実行

```
npm test
```

2.下記の表示が出ればok

```
 PASS  __tests__/src/data_fetchers/QuizFetcher.js
  QuizFetcherのテスト
    ✓ クラスチェック (11 ms)

  console.log
    @@@@@@

      at Object.<anonymous> (__tests__/src/data_fetchers/QuizFetcher.js:5:13)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.775 s, estimated 1 s
Ran all test suites.
```

github：https://github.com/facebook/jest
Railsアプリのデプロイで「応答時間が長すぎます。」のserver errorに出くわした話


#概要
Railsアプリを本番環境(AWS/EC2)にデプロイしようとIPアドレスでサーバーへ接続した際、「このサイトにアクセスできません。応答時間が長すぎます」とのエラーで長時間ハマったため、備忘録　兼　同じ境遇の方の参考になればと思い投稿しました。
![erorr.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/746705/75809b93-1ab9-5c7d-d4b2-b6741ca8a31c.png)



#実行環境
・Rails  v5.1.7
・Ruby   v2.7.0
・mysql
・AWS, EC2(本番環境)
・unicorn
・nginx

#結論 : config.force_ssl = true を有効にしていたことが原因

```ruby:config/production.rb
config.force_ssl = true
```
を

```ruby:config/production.rb
config.force_ssl = false
```
 に変更することで改善出来ました。

## config.force_ssl って何?

ずばり、IPアドレスへのアクセスを全てhttps形式として通信させる設定です。

つまり、意図せずとも自動でhttps形式になるということ。

こちらのコードは本番環境上の設定を決めるconfig/production.rbファイル内にあります。　config.force_ssl = true のコードは通常コメントアウトされているのですが、開発中に外したことが原因となっていました。

今回私が立てたAWSのEC2サーバーは、通信形式をhttp形式のポート範囲でのみ設定しており、許可していないhttps形式で延々とアクセスしていたことで、「応答時間が長すぎます」とのエラーが発生したのです。同じ症状で悩んでいる方は、一度EC2のセキュリティグループ設定と上記のファイルを確認してみるといいかもしれません。

##解決までにやったこと

余談ですが、今回の件でエラー解消に関する知見が深まったので、自分なりに学んだポイントを書かせて頂きます。

サーバー通信エラー解決のポイント
①問題が起きているサーバーがどこなのかを特定する
②問題が起きているサーバーのログを読む
③ログを読んでもわからない場合は怪しいところをコピペしてひたすらググる！笑

もう少しだけ掘り下げて書いていきます。

①について
クライアントがwebサイトにアクセスしてからアプリケーションが表示されるまでにどのような処理が行われているのか調べ以下の構造になっていることを学習しました。上から順に接続していき、アプリケーションを起動するようです。
色々な記事で、Nginx➡︎Unicornの順に起動すると書いていることに対して何も考えていませんでしたが、調べてやっと理解することが出来ました。

・開発環境(今回の場合EC2)
　⬇︎
・webサーバー(今回の場合Nginx)
　⬇︎
・アプリケーションサーバー(今回の場合Unicorn。このサーバーの中にアプリがあります)

そして、正しくアクセス出来ているか上記の順番で1つずつ確認しました。

結果として、記事前半の内容が原因でEC2➡︎Nginxへの通信が出来ていないことを突き止めることが出来ました。

②について
・開発環境
ローカル環境の場合ここは問題ないかなと思います。EC2等クラウドサーバーの場合、インターネットゲートウェイ/ルートテーブル/セキュリティグループ等、通信の設定によりこのサーバーと接続出来ないことも。まだ十分に理解出来ていないので詳細は控えます。

・webサーバー(私の場合ここが原因でした)
Nginx、Unicorn、デプロイするアプリ全てインストールし、2つともサーバー上で起動出来ているにも関わらずエラー発生。何度見直しても間違いがわからず手詰まりでしたが、Nginxログが解決の糸口となりました！

・nginx.access.log
・nginx.error.log
・Unicorn.log
・production.log

nginxやunicorn、railsアプリも、リアルタイムでアクセス履歴を記録してくれる上記ファイルが自動作成されています。私自身最近まで知らなかったのですが、ローカル環境のターミナルでrails s したあとに出るアレと同じものが用意されているのですね。私の場合、クローンしたアプリ直下のlogディレクトリ内にありました。
(nginxのconfファイルで設定している場所に生成されるようなので、人によって違うかもしれません)
それでは中身を確認しましょう！

```
tail -f /var/www/rails/アプリ名/log/nginx.access.log
```

※tail -f :ファイルの最後に追加される文字を表示するコマンド
(エラーが特定しづらい場合はcatコマンドで全て表示させて確認してください)

上記コマンドでnginx.access.logを表示し、ブラウザでアクセスしながら再度logを確認。
すると、何度試みてもlogの内容が更新されていないことに気付きました。
ここで初めて、Nginxに接続出来ていないこと(EC2サーバー➡︎webサーバーの通信が上手くいっていないこと)がわかり、ググって記事を漁り、なんとか解決に至りました。
ログを確認することの大切さをここでやっと理解しました。
また、今回は活用する機会がありませんでしたが、Nginxにアクセス出来ていると確認出来た場合は
同ディレクトリのnginx.error.logの中身を確認。

```
tail -f /var/www/rails/アプリ名/log/nginx.error.log
```

エラーが起きている場合、Nginxのサーバー内での問題の可能性があります。
(Webサーバー➡︎アプリケーションサーバーの通信)

エラーがない場合は、アプリケーションサーバーもしくはアプリ内で問題が起きている可能性があります。
同ディレクトリのunicorn.log、production.log(アプリ内のログ)それぞれ、同様の方法で確認しましょう。

あとは③の通り、ログで見つけた怪しい部分をひたすら読む、ググるの繰り返しです笑
それでも解決出来ないことは多々あると思いますが、これが今回学んだエラーの解決フローです。

##最後に

拙い記事にも関わらずここまで読んで頂きありがとうございます！
この記事が少しでも誰かのエラー解決の手助けになれば幸いです。
また、まだまだ勉強不足で間違っている部分があるかもしれません。何かあればコメントでご指摘頂ければと思います。

##参考記事

railsアプリをAWSへデプロイするうえで、こちらの記事を参考にさせて頂き、完遂することが出来ました！どちらの記事も画像や細かいポイント付きでとてもわかりやすかったので、実行環境がマッチしている方は是非参考にしてみてください！

https://qiita.com/naoki_mochizuki/items/f795fe3e661a3349a7ce
https://qiita.com/Yuki_Nagaoka/items/975b7598806d6ae0c0b2
seleniumとheadless-chromiumを使ってaws上で情報送信botを作った話

基本的には、以下のページを元に作成していきました。
何点か躓いた場所があったので、その点だけ備忘録として残しておきます。


> 毎朝5時にGoogle Formに自動回答したい
> https://qiita.com/kota-yata/items/9d4124ec7a7dd4e3d4f0

> AWS Lambda(Python)でSelenium + Headless Chromeの実行
> https://masakimisawa.com/selenium_headless-chrome_python_on_lambda/


## つまづいた点
### headless-chromiumのサイズオーバー
#### 詳細
layerへのuploadの上限が50MBであったが、最新バージョン(v1.0.0-57:2020/11/21時点)のサイズが50MB以上あり、lambdaのlayerへのupload上限である50MBを超えてしまっていた。

#### 対応
一つ前のバージョン（v1.0.0-55）の方がサイズが小さく、45MBほどであったため、そちらを採用した。

https://github.com/adieuadieu/serverless-chrome/releases/ 参照。

### .fontフォルダがアップロード不可
#### 詳細
手動でlayer登録をしようとすると、フォルダアップロード時に、.で始まるフォルダが表示されず選択できない
#### 対応策
コマンドから登録できるようにしたい。面倒くさかったのと、これをせずとも情報送信くらいはできそうだったので、skipした。


### lambda関数のメモリ不足によるタイムアウトエラー
#### 詳細
上ページを参考にコーディング・セッティングを行なったが、lambda上でタイムアウトエラーが発生した

#### 対応
待ち時間を10分にし、メモリサイズを512MBとして解決
Vuexとは

# Vuexとは
- Vue.jsアプリケーションのための開発されたアプリケーションの状態(state)を管理するためのソフトウェア
- 状態管理を行うためのライブラリ
	
## メリット
- データの流れを見やすくすることでバウの少ない
- デバッグのしやすい状態管理を実現すること
		
## デメリット
- コードが冗長
- 学習コストの発生

# 2つのモジュールモード

## クラシックモード
- Vuexを導入する基本的なモード
- 1つのファイル(index.js)に記述
		
## モジュールモード
- より本格的な大規模アプリケーションを使うときのモード
- 複数のファイルに記述できる

### モジュールモード動作の条件
- index.jsがストアオブジェクトをexportしない
- または、index.jsがstoreフォルダは以下に存在しない
		
# Vuexを利用するタイミング
中規模から大規模のSPAを構築する場合
	
# 用語：State(ステート)
- アプリケーションの状態を保持
- 信頼できる唯一の情報源
- 直接操作はルール違反
	
# 用語：Actions (アクション)
- 外部APIとの通信を行い、ミューテーションを呼び出す役割
- 非同期処理必要なときはここに書く
	
# 用語：Mutation(ミューテーション)
- Vuexのストアの状態を唯一変更できる存在
PowerShellとは？


#PowerShellが全く分からない初心者向け
PowerShell・・・？力を持った貝・・・？という人向け。


#PowerShell とは
・**言語**および、**CUI**である。
・Microsoftが開発。
・PCで行うほとんどの操作を行うことが出来る。
・.Net系のライブラリーを使用することができる。
・Microsoftサービスも操作できる。
・WordやExcelなどの反復作業などをバッチ化出来る。
・DB操作も可能。（※DBによる。Oracleに関してはネットによく落ちている）


##*余談　CUIがわからない人向け
CUIとGUIってなに？って人のために例を紹介。

**・CUI操作**とは、**コマンド**でPCを操作すること
例）CUI操作での新規フォルダ作成
　　コマンドプロンプトを起動させて、**mkdir フォルダ名**と入力。
→マウスがなかった時代、PCへの命令はこのCUI操作で行っていました。


**・GUI操作**とは、**マウス**で画面をポチポチして操作すること
例）GUI操作での新規フォルダ作成
　　マウスを右クリックして[ 新規作成 ] → [ フォルダの作成 ]をクリック
→今の時代、当たり前に使用しているのがGUI操作ですね。





##PowerShellはコマンドプロンプトをもっといい感じにしたやつ！
- コマンドプロンプトはパイプにテキストしか渡せない。
- PowerShellはオブジェクトを渡せる。


##実行ポリシーに関して
PowerShellはデフォルトで実行できません。
以下のようなコマンドを打ち、実行ポリシーを変更する必要があります。
実行ポリシーはむやみに変更するべきではありません、現場責任者の判断を受けよう！
自分で購入したPCだったら自己責任で好きなように変更してもいいかなあ。。。

（コマンドプロンプトなどで実行。）
Set-ExecutionPolicy RemoteSigned -Scope Process -Force

↓実行ポリシーに関しての公式ドキュメント
https://docs.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_execution_policies?view=powershell-7.1


##かんたん！PowerShellでプログラム作ってみよう
###ps1ファイルを作成する
新しいテキストファイルを作成し、拡張子をps1に変更するだけ！
そこにコードを記述していきます。

###ps1ファイルにプログラムを記述する
**・1-1 新規フォルダ作成プログラム**
`New-Item C:\powershell_workspace\ -itemType Directory`
(補足) New-Item フォルダ名(powershell_workspace) -itemType Directory

パワーシェルファイル(ps1)をダブルクリックするだけで、実行できます。

**・1-2 新規ファイル作成プログラム**
`New-Item C:\powershell_workspace\piyo.txt`
New-Item ディレクトリ＋ファイル名


##開発環境に関して
・vs-code 
・PowerShell ISE

今回の記事に関しては、プログラムが基礎的なため、メモ帳などでコードを記載するだけで済みます。
しかし実際に運用に用いるとなるとメモ帳などではいまいちです。
なので、**vs-code** や**PowerShell ISE**を使用してプログラミングしていくことが現実的です。


PowerShell ISEはインストール不要でデフォルトで搭載されています。
PowerShell ISEでも容易にデバックが出来ますが、
オブジェクトに何が入っているのかいまいちわかりにくいので、
vs-codeのほうが使いやすいように感じます。超個人的な意見ですが。
環境変数に入れたやつを反映させる vuejs .envの使い方

###環境変数に入れたやつを反映させる vuejs .envの使い方
環境変数に入れるのはAPIの大事なキーとかだった気がする

環境変数ファイルを作成
ドキュメント
https://cli.vuejs.org/guide/mode-and-env.html#environment-variables

VUE_APP_TITLE=My Appこんなかんじで使うらしい


```
.env　●作成

VUE_APP_TITLE=Vuetify Todo //●作成＝〇〇をタイトルとかに使っていく

```

たくさん使うので、ストアに入れて、汎用性をもたせる
アクセスにはこんなかんじらしい
process.env.VUE_APP_NOT_SECRET_CODE・・・・


```store.js
export default new Vuex.Store({
  state: {
    appTitle:process.env.VUE_APP_TITLE,//●ステートのデータに環境変数envにアクセスしていれる名前はappTitle
```

```app.vue
 <v-toolbar-title class="text-h4 ml-4">
      {{$store.state.appTitle}} //●ストアーにアクセスして表示させる
  </v-toolbar-title>

```

こんなかんじで反映できた

![スクリーンショット 2020-11-22 16.10.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/898667/43e4d52d-406a-602a-5944-3a4337dea102.png)



環境変数は未だによくわからんけど、プログラムで使う大事なAPIのキーとかをいれていたような。。。
今後かなり重要そうなので、メモしました
1年半研究室で強化学習をやった人の解説

#要約
始めてのQiita投稿
とりあえず知っている知識を共有
強化学習がどういったものなのか、簡単に説明

#大まかな流れ
1. 機械学習
2. 強化学習の枠組みの説明
3. 強化学習で用いられる記号などの意味の説明
4. マルコフ決定過程（Markov Decision Process: MDP）
5. 収益
6. 状態価値
7. 行動価値<br>
この記事ではとりあえず1,2を。

#機械学習
機械学習分野のうちの1つの分野である。メジャーなものをあげると

- 教師あり学習
- 教師なし学習
- 強化学習

があげられる。
それぞれの説明を軽く挙げると以下のようになる。

##教師あり学習
分類わけなどで使われている。学習するためのデータに教師(答え、正解)が存在しており、その答えを毎回確認しながら学習していく手法になる。
例えば、犬の種類を教えてくれるAIを作るなら、学習データにはそれぞれどのデータがどの犬種かをラベル付けして学習させる。ただ、学習データに存在しない犬種は正確な答えを教えてくれない。

##教師なし学習
教師あり学習と異なり、学習データに正解のラベルを付けないで学習する手法。AIが自律的に学習をし、正解を認識するようになる。例えるなら、小さい子供が毎日いろいろなものを見ていくうちに、自然と認識していくようになる、みたいな学習の仕方をしている。

##強化学習
今回のメイン。上2つと違うのは、正解を与える代わりに、「価値」というものを計算し、「収益」を最大化するモデルになる。有名な強化学習モデルだと、AlphaGoなどがあげられる。本記事では、この強化学習で出てくる様々なものをあっさり説明し、これから強化学習をやろうと思っているひとにも分かるような説明をしていこうと思う。

#まず枠組み
強化学習はエージェントと環境が存在する。
エージェントは実際に学習するプレイヤーになる。環境はそのプレイヤーがやるゲームだと思ってもらえばよい。
下にある画像は強化学習の枠組みである。
1. エージェントが行動をする
2. 状態が変わる（遷移）する
3. 遷移先の状態にある報酬と、遷移先の状態の情報をエージェントに渡す
1,2,3をずっと行うことで学習することができる。

![Imgur](https://i.imgur.com/YOff4Kj.jpg)

ここで具体的な例をあげようと思う。例えば、マインクラフトで迷路をやるとする。
状態になるのはマインクラフトの1ブロックで、行動は前後左右の4方向になる。
エージェントは実際に迷路を解くプレイヤーとなり、エージェントは実際に迷路を解きながらその状態がどれくらい良い場所なのかを評価しながらゴールを目指す。
報酬とはエージェントに与えられる褒美のようなもので、報酬によってエージェントは学習をしてくと言っても過言ではない。報酬の設定の仕方は様々あり、行動をするごとに報酬を与えることもできれば、ゲームをクリアしたときのみに与えることもできる。
強化学習の目的は、この報酬の合計、すなわち収益を最大化するために、行動選択を学習することになる。


次回の記事では実際にどうやって学習していくのかを表していこうとおもう。

#参考文献
https://www.irasutoya.com/
https://collegestudenttextbook.org/product/reinforcement-learning-an-introduction-2nd-edition-pdf-ebook/
https://qiita.com/PlanetMeron/items/63ac58898541cbe81ada
https://qiita.com/Qiita/items/c686397e4a0f4f11683d
STM32 nucleoを使う (3)  EXTI割り込み

#はじめに
SWの検出を割り込みで行うプログラムについて記述します。
前回のプログラムを改造していきます。
STM32にはGPIOの割り込みはEXTIを使います。EXTIとは拡張割り込み／イベントコントローラのことです。信号の立上り/立下りの検出を行い割り込みを発生させます。

#EXTIの設定
iocファイルのSwAndLedTest.iocを開きます。
![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68712/35c51287-94bc-ee79-5893-92853ab0d32d.png)
GPIOのコンフィグレーションを開きます。
GPIOモードをFalling edgeからRising/Falling Edgeに変更します。
![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68712/017aa470-6705-b188-0efa-63d78fe5e139.png)
NVICのコンフィグレーションを開き、EXTI Line[15..10] interruptsにチェックを入れます。
外部割込みを有効とします。
![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68712/c4230f88-deb9-0599-2802-257823be7e0f.png)
iocファイルを保存するとコードを生成するか確認が入るので、Yesを選択しコード生成をします。

#割り込みハンドラ
割り込みの処理は割り込みハンドラに記述します。
stm32f3xx_it.cに各割り込みハンドラがありますので、EXTI line[15:10]の割り込みハンドラのEXTI15_10_IRQHandlerを探します。内容は以下のようになっています。
ここの/* USER CODE BEGIN EXTI15_10_IRQn 0 */と/* USER CODE END EXTI15_10_IRQn 0 */に割り込み処理を書いてもよいですが、もう少し内容を見てみます。

```
void EXTI15_10_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI15_10_IRQn 0 */

  /* USER CODE END EXTI15_10_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);
  /* USER CODE BEGIN EXTI15_10_IRQn 1 */

  /* USER CODE END EXTI15_10_IRQn 1 */
}
```
HALのEXTIの割り込みハンドラHAL_GPIO_EXTI_IRQHandlerを呼んでいます。

```
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
  /* EXTI line interrupt detected */
  if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u)
  {
    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
    HAL_GPIO_EXTI_Callback(GPIO_Pin);
  }
}
```

割り込みをクリアする関数とEXTIのコールバック関数HAL_GPIO_EXTI_Callbackを呼んでいます。
HAL_GPIO_EXTI_Callbackの内容は以下の通り。

```
/**
  * @brief  EXTI line detection callback.
  * @param  GPIO_Pin Specifies the port pin connected to corresponding EXTI line.
  * @retval None
  */
__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(GPIO_Pin);

  /* NOTE: This function should not be modified, when the callback is needed,
           the HAL_GPIO_EXTI_Callback could be implemented in the user file
   */
}
```
このコールバック関数にはweakシンボルが付いています。他でHAL_GPIO_EXTI_Callbackが定義されていない場合はweakが付いた関数が使われますが、他で定義されている場合は使われません。
割り込み処理を記述するには、HAL_GPIO_EXTI_CallbackのコメントにあるようにユーザーファイルにHAL_GPIO_EXTI_Callbackを作成するのが良いでしょう。

#HAL_GPIO_EXTI_Callbackの作成
main.cの/* USER CODE BEGIN 0 */と/* USER CODE END 0 */の間に記述します。
前と同じだと違いが判りませんので、押している間は消灯するように変更します。

```
/* USER CODE BEGIN 0 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  if (GPIO_Pin == B1_Pin)
  {
    if (HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin) == GPIO_PIN_RESET)
    {
      HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
    }
    else
    {
      HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
    }
  }
}
/* USER CODE END 0 */
```

pin15-10の割り込みが共通なので最初にB1による割り込みかどうかを判定しています。
立下り/立上りの割り込みとしたので、ピンの状態でLEDの点灯/消灯を決定しています。

mainルーチンからは処理を削除します。
何もしない無限ループとします。

```
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    ;
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
```

#実行
RUNボタンで実行します。
起動時は割り込みが発生していないのでLEDは消灯しています。
ボタンを押し離したときにLEDが点灯します。
その後は、押すと消灯し離すと点灯します。
【Java】Javadocってなに？

#プログラミング勉強日記
2020年11月22日
授業でJavadocを元にコードを書いたことはあるが、Javadocについて理解できていないのでまとめる。

#Javadocとは
　JavaではJavadocというコメントを記述することができ、プログラムについて説明するドキュメントをソースコードに埋め込むためのものである。プログラムの説明をソースコードに埋め込むことができない場合、プログラムの説明文は別のファイルで管理することになり、コード用のファイルと説明ファイルの両方の管理が必要になる。しかし、この場合は修正時にドキュメントの更新を忘れてしまい、説明と動作が一致しないということが起きる可能性がある。Javadocをうまく使うことで、コードの修正時にドキュメントの修正もできる。
　Javadocはクラスの概要やメソッドの概要を記述しておくと、その情報からHTML形式のドキュメントファイルを生成してくれる。

　Javadocコメントを書く場合は`/**`と`*/`の間にコメントを記述する。

```java:Javadocコメント
/**
Javadocコメント
*/
```

##サンプルコード

```java
/**
 * @author Tanaka Taro
 * @version 1.0.0
 */
 
 /**
  * Javadoc解説用のメインクラス
  */
public class Main {
    /**
     * mainメソッド
     * @param args 使用しない
     */
    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}
```

#Javadocのタグ名
　Javadocには`@`がついたタグが用意されている。

| タグ名   　　　　   | 説明　|
|:-------------:|:--------------------:|
| `@author`      | クラスの作成者　|
| `@version`     | 作成したプログラムのバージョン |
| `@param`       | メソッドの引数の説明　|
| `@return`      | メソッドの返り値の説明 |
| `@throw`       | 発生する例外クラスを指定 |
| `@serial`      | 直列化されたフィールドの説明 |
| `@sesrialData` | 直列化された状態でのデータ型と順序 |
| `@since`       | 初めて作ったときのバージョン |  



#参考文献
[いまさら聞けない「Javadoc」と「アノテーション」入門 (1/4)](https://www.atmarkit.co.jp/ait/articles/1105/19/news127.html)
[【Java入門】コメントの種類と書き方(Javadocに関する規約も解説](https://www.sejuku.net/blog/65556)
[Javadocタグ](https://www.javadrive.jp/javadoc/tag/)
Rails チュートリアル_1章_ 学習メモ

#学んだ事
##Git
###開発のログを記録するためのシステム
誰がいつ何を変更したのか、修正したのか、作成したのか分かるように記録しておく。
###リポジトリとは
>リポジトリ（repository）とは、ソースコードや変更履歴、コメントなどを一括して保管する場所です。リポジトリには、自分のPC上に作る「ローカルリポジトリ」と、「GitHub」などのWebサービス上に作る「リモートリポジトリ」があり、両者を連携させることで複数の開発者による開発を1本にまとめることができます。
####git init
```git init```はリポジトリを新規作成する、既存のリポジトリを初期化するコマンド
####git add -A
現在のディレクトリにあるファイルすべてをリポジトリに追加する。まだ実行はされずに追加するだけ→```commit```コマンドを待つ状態となる。
####git status
何が変更されたのか、されなかったのか、確認する
####git commit
待機状態となっている変更内容をリポジトリに反映する。```commit -m 〇〇```とするとコメントを追加する事が出来る。

##Github
Gitのバージョン管理履歴をオンライン上で見れるようにする。→Gitのオンライン版という理解。
###目的
+ ソースコードのバックアップのため
+ 誰もが見れる事によって共同開発を容易にするため
####ブランチ
リポジトリのコピーのようなもの。本リポジトリを編集せずにテスト的な容量で編集する際に使う。
親リポジトリはmasterブランチと呼ばれる。

##Heroku
デプロイに使われる一種のツールの事
###デプロイって何
作成したプログラム等を「使える状態」に公開する事。
個人的にはリリースなどと似た理解をしている。
自分のPC上だけで動くプログラムからユーザーや他人が使用して動く状態にする事。
##Gemファイルとは
プログラムを作成する上で便利な機能の事でライブラリとも呼ばれている。iPhoneでいう、既に容易されているショートカットの事という理解。
※自分でショートカットを作成する必要がない。
###bundleとは
bundleもgemの一種で様々なgemの管理を行っている。
インスールしたりアップデートしたり。

#演習
##1.3.4
###1.
helloアクションのrenderメソッドの中身をhelloからhola,mund！に変更する
###2.
+ ```render html: goodbye,world!```と返すgoodbyeアクションを追加する。
+ ルーティングの#アクション名をhelloからgoodbyeに変更する

#起きたエラーと解決
##演習１．３．４_3.
###Template is missing
rederメソッドで返す表示が無いと言われた
goodbyeアクションを見てみると、renderの後にｈｔｍｌ：がなかった事で、ファイルを指定出来ていなかった。
JavaScriptで勉強時間を伸ばすボタン作ってみた！

**休憩したくなったら押すだけです！**

永遠と「休憩」がでなければ、ひたすら勉強できますよ笑

![Screen Recording 2020-11-22 at 03.46 PM.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/896901/28e70daa-01ea-56b6-fe5f-d3cafad000ae.gif)

```index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title>GAME</title>
    <link rel="stylesheet" href="css/styles.css">
  </head>
  <body>
    <h1>押してね！</h1>
    <div id="btn">?</div>
    <script src="js/main.js"></script>
  </body>
</html>
```

```styles.css
h1 {
  text-align: center;
}

body {
  background: #efefef;
}

#btn {
  width: 200px;
  height: 200px;
  background: #ef454a;
  border-radius: 30%;
  margin: 30px auto;
  text-align: center;
  line-height: 200px;
  color: white;
  font-weight: bold;
  font-size: 42px;
  cursor: pointer;
  box-shadow: 0 10px 0 #d1483e;
  user-select: none;
}

#btn:hover {
  opacity: 0.9;
}

#btn:active {
  box-shadow: 0 5px 0 #d1483e;
  margin-top: 40px;
}
```

```main.js
'use strict';

{
  const btn = document.getElementById('btn');
　
  btn.addEventListener('click', () => {
    const n = Math.floor(Math.random() * 3);

    switch (n) {
      case 0:
        btn.textContent = '休憩';
        break;
      case 1:
        btn.textContent = 'もう10分';
        break;
      case 2:
        btn.textContent = 'もう15分';
        break;
    }
  })
}
```

JavaScriptほんと楽しい(^^)

###参考
[JavaScriptでおみくじを作ろう](https://dotinstall.com/lessons/omikuji_js_v5)
AWSのEC2インスタンスにカラム名の変更が反映されているのに変更前のカラム名がunknown attributeだというエラーが出る

## 起きたこと
データベースのカラムを変更するため、マイグレーションファイルを書き換えました。
その後、自動デプロイツールであるCapstranoでデプロイを更新しました。
動作を確認したところ、カラムを変更したフォームに入力する画面に遷移しようとした時に、unknown attributeというエラーが出ました。

## 結論
teratailで質問をしたところ「アプリケーションサーバーの再起動はできているのか」とアドバイスいただきまして、Unicornのプロセスを確認したところ起動していませんでした。
Uniconが起動していなかった原因はわかりませんが、起動したところエラーがなくなり変更したカラムにも値が保存されるようになりました。下の図のようにアプリケーションサーバーが起動していなかったため、ビューなどは表示できたが、処理を行ったりDBへアクセスができずエラーになったと考えました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693815/7715dddd-f64c-812d-1793-315864b49080.png)

teratailでの質問：https://teratail.com/questions/304282


## 質問前に行ったこと３つ
### 1. DBのカラム名確認
EC2内のDBであるMariaDBの中身を確認しました。

```
[ec2-user@ip-..... ~]$ mysql -u root -p
```
でデータベースにアクセスした後は

```
USE アプリ名_production
```
でデータベースを指定し、

```
DESCRIBE テーブル名
```
で確認するとカラムがみられます。
これでチェックしたところ、変更されていました。

## 2.データベースとWebサーバーのリスタート
```
[ec2-user@ip-・・・・ ~]$ sudo systemctl restart mariadb 
[ec2-user@ip-・・・・ ~]$ sudo systemctl restart nginx
```
これでも変わりませんでした。

## 3. データベースをリセット
投稿していた中身は消えてしまいますが、以下の記事を参考に、EC2インスタンスのcurrentディレクトリに移動した後、以下の４つを実行してリセットしました。

```
$ RAILS_ENV=production DISABLE_DATABASE_ENVIRONMENT_CHECK=1 bundle exec rake db:drop
$ rake db:create RAILS_ENV=production
$ rake db:migrate RAILS_ENV=production
$ rake db:seed RAILS_ENV=production

```
参考：https://qiita.com/iczo32/items/84719b5aff8a6b9e37bd


以上
Golangはじめて物語(第5話: DynamoDBで1MB以上のアイテムリストをクエリする)

# はじめに
Golang ＋ DynamoDB は高速で便利！だが、DynamoDB のアトリビュートと Golang の map の関連が分かりにくかったり、慣れないとハマりどころがけっこうある。

今回は、1MB以上のアイテムリストを取得するクエリを発行する場合のコードを書いてみる。

# DynamoDBのテーブル定義
以下のようなテーブルを用意する。
- idをハッシュキーとする
- nameをレンジキーとする
※実際のデータモデルでこんなものは滅多にないと思うが、同じIDに複数の名前が連なっているというモデルを考える。

今回、簡略化するために、同一 ID で異なる 1000Byte の name 1500 レコードある状態で、ID 指定のクエリを発行して、name の一覧を取得するような Golang のソースを書く。

# ソースコード
```golang
type item struct {
    Id   string `dynamodbav:"id"`
    Name string `dynamodbav:"name"`
}

func main() {
    var (
        LastEvaluatedKey map[string]*dynamodb.AttributeValue
    )

    sess := session.Must(session.NewSessionWithOptions(session.Options{
        SharedConfigState: session.SharedConfigEnable,
    }))

    svc := dynamodb.New(sess)

    for {
        result, err := svc.Query(&dynamodb.QueryInput{
            TableName: aws.String("[テーブル]"),
            KeyConditionExpression: aws.String("#ID=:id"),
            ExpressionAttributeNames: map[string]*string{
                "#ID": aws.String("id"),
	    },
            ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{
	        ":id": {
	            S: aws.String("00001"),
	        },
            },
            ExclusiveStartKey: LastEvaluatedKey,
	})
        if err != nil {
	    log.Println("Got error calling Query:")
	    log.Println(err.Error())
	    return
        }
		
        log.Println(result)

        if len(result.LastEvaluatedKey) == 0 {
            break
        } else {
            LastEvaluatedKey = result.LastEvaluatedKey
        }
    }

    return
}
```

## LastEvaluatedKey
DynamoDB は1回の Query 関数で取得し切れない場合、「ここから続けてね」という情報を QueryOutput 構造体の LastEvaluatedKey に格納して返してくる。
この情報を持ち廻って、Query の ExclusiveStartKey に設定することで、次の Query では続きを取得してくれる。

なお、LastEvaluatedKey が設定される場合は以下のような中身になっている。

```JSON
  LastEvaluatedKey: {
    name: {
      S: "01022xxxxx(中略)xxxxx"
    },
    id: {
      S: "00001"
    }
  },
```

では、このレコードは初回呼び出しと次の呼び出し、どちらに格納されるかというと、初回側に

```JSON
  Items: [
    {
      id: {
        S: "00001"
      },
      name: {
        S: "00001xxxxx(中略)xxxxx"
      }
    },
    (中略)
    {
      id: {
        S: "00001"
      },
      name: {
        S: "01022xxxxx(中略)xxxxx"
      }
    }
  ],
```

といった具合に、Item 配列の最後に同じレコードの情報が格納されていて、2回目呼び出しの Item 配列には上記レコードが含まれていない。要は、重複や漏れを考える必要なく、Item 配列を扱っておけば、取得したアイテムリストはそのまま使えると考えれば良い。

LastEvaluatedKey は初期化した状態で渡せば、クエリのオプションで指定しなかった場合と同等の動作となるため、上記のコードは先に LastEvaluatedKey を宣言しておき、do while 的なループの回し方をしている(Golang には do while がなく for に一本化されているので、上記のような方式となる)。

Lambdaで扱う場合、Golang の var で毎回初期化してくれるかが分からないので、ループに入る前に一度初期化しておくのが安全だろう。

これで、大量データを処理するクエリも問題なく扱えるようになった！
〔備忘録〕プログラミング事始め

#はじめに
現在私は自然科学系の調査を生業としています。そこまで解析が困難な膨大なデータを扱うわけではなく、データ解析にはエクセルがあればほぼ十分。少し難しい解析はRがあればほぼすべてをカバーできるような状況です。ただ、最近機械学習だとか、電子工作だとか、業務の自動化だとか目にすると先々なにか役に立つのではないかということでプログラミングは未経験だけどなにか初めて見ようかなと思った次第です。

#勉強したいこと
1.python
機械学習に特化しており、自分の業務になんらかの関連性を見出したからです。
2.電子工作
ArduinoとかESP8266とかラズパイとか。先端技術とは程遠いわが研究分野になんらかの光をさしてくれそうだから。

#心掛けること
今までは本ばっかり読んでなんらアウトプットはしてきませんでした。なるべく勉強結果をそのまま記載するでもいいからアウトプットを心掛けるようにしたいです。アウトプットしないとまったく覚えていられないんです。いつまで続くかはわかりませんが頑張りたいです。
Cloud Native Buildpacksでコンテナイメージをサクッと作成する

# Cloud Native Buildpacks
[Cloud Native Buildpacks](https://buildpacks.io/)はアプリケーションのソースコードから任意のクラウドで実行できるイメージに変換してくれるツールです。プロジェクトは2018年1月にHerokuによって開始され、2018年10月にCloud Native Computing Foundation(CNCF)のsandbox projectsになりました。
※2020/11/22時点でCNCFのprojectsを確認したところ、[Incubating projects](https://www.cncf.io/projects/)に移動しており成熟度が上がっているようです。

また関連して、米国時間:2020/10/10にGoogle CloudからオープンソースのBuildpacksとビルダーのサポートする[記事](https://cloud.google.com/blog/ja/products/containers-kubernetes/google-cloud-now-supports-buildpacks)も上がっておりました。

# 使ってみる

Buildpacksする際にpack commandを使用するため、まずpack CLIをインストールします。

```bash
brew install buildpacks/tap/pack
```

今回は試しにBuildpacksのsample集にあるRuby projectを使ってコンテナイメージを作成します。

```bash
git clone https://github.com/buildpacks/samples
cd samples/ruby-bundler
```

コンテナイメージを作成するには`pack build`で作成することができます。Dockerfileなしでコマンドひとつでできるのは嬉しいですね。

```bash
pack build myapp --builder cnbs/sample-builder:bionic
```

作成が完了したら、サンプルのsinatraアプリケーションを立ち上げて見ましょう。
下記コマンド実行後、`localhost:8080`を確認して`Hello World!`が出ていれば成功です。

```bash
docker run -it -p 8080:8080 myapp
```

# 最後に
次は一からBuildpack作るとこまでやりたい。

# 参考資料
[Buildpacks.io](https://buildpacks.io/)
[Cloud Native Computing Foundation | Graduated and incubating projects
](https://www.cncf.io/projects/)
Laravel：SQLSTATE[42000]Syntax error or access violation...bytesの解決

#【概要】

<b>1.[結論](#1結論)</b>

<b>2.[SQLSTATE[42000]とは何か](#2sqlstate42000とは何か)</b>


<b>3.[なぜこのエラーになったのか](#3なぜこのエラーになったのか)</b>

<b>4.[どのように解決したのか](#4どのように解決したのか)</b>

<b>5.[参考URL](#5参考url)</b>

<b>6.[開発環境](#6開発環境)</b>



#1.結論
<b>`app/Providers/AppServiceProvider`</b>の<b>`public function boot()`</b>に<b>`Schema::defaultStringLength(191);`</b>を記載する！

#2.SQLSTATE[42000]とは何か

アクセス違反ですという意味で、SQL文の文法に誤りがあるということです。ただ、それに起因してデータがパンパンになっているためこのエラーになっています。

#3.なぜこのエラーになったのか
結論から言いますとLaravelとMysqlのバージョンのせいで、Mysqlのカラムや中身の文字列がデータ量(767bytesがMAX)を超えたからでした。UTF8MB4になり1文字あたりのデータ量(4bytes)が増えたからのようです。
(大変参考になったURLを下記([参考URL](#5参考url))に添付しています。)

#4.どのように解決したのか

```php:app/Providers/AppServiceProvider
use Illuminate\Support\Facades\Schema;　//⬅︎を追加記載(❶)
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
// 省略
    public function boot()
    {
        Schema::defaultStringLength(191);　//⬅︎を追加記載(❷)
    }
}
```
4bytes*191文字=764bytesに抑えることで、規定量以下にしました。これをデフォルト設定にしているのでどのテーブルにもこれが適用されます。Mysqlのバージョンアップもありましたが、手軽かつアプリを使用する際に100文字を超える実装はなかったので今回はこの手段を取りました。また❶を記載しないとエラーが起きます。

#5.参考URL
<a href="https://qiita.com/beer_geek/items/6e4264db142745ea666f">①Laravel5.4以上、MySQL5.7.7未満 でusersテーブルのマイグレーションを実行すると Syntax error が発生する</a>
<a href="https://www.suzu6.net/posts/213-migrate-skip-if-exist/">②【Laravel】migrateでテーブルが存在したらスキップする</a>


#6.開発環境
PHP 7.4.10</br>
Laravel 8.9.0</br>
MySQL 5.6.47/SequelPro 1.1.2</br>
Microsoftアカウントを持たないユーザーを追加　方法


Windowsの設定→アカウント→家族とその他のユーザー

【その他のユーザーをこのPCに追加】を選択

【ユーザーのサインイン情報がありません】を選択

【Microsoftアカウントを持たないユーザーを追加する】を選択

ここのユーザー名がユーザーのフォルダ名になる
Rails 子レコードの作成・更新時に親レコードのupdated_atも更新する


こんにちは。
初めて記事を投稿してみます。

Railsで子レコードを作成・更新時、親レコードのupdated_atも更新したい時
ActiveRecordの関連付けで、touchオプションを使えば簡単にできること知ったので
備忘のためにまとめてみます。

##touchオプション

Railsガイドより
>:touchオプションをtrueに設定すると、そのオブジェクトがsaveまたはdestroyされたときに、関連付けられたオブジェクトのupdated_atタイムスタンプやupdated_onタイムスタンプが常に現在の時刻に設定されます。

```ruby
class Shop < ApplicationRecord
  has_many :reviews
end

class Review < ApplicationRecord
  belongs_to :shop, touch: true
end

review = Review.last
review.update( title: "いいお店")
=> # review.shop.updated_atも更新する
```

##利用シーン

###キャッシュの無効化

このためにtouchオプションを使うのが一番多いようです。
Russian Doll Cachingという、ネストされたフラグメントキャッシュの内側のキャッシュ(review)が更新されると、外側のキャッシュ(shop)も更新してくれる機能で、子のmodelにtouchオプションをつければ有効になります。
キャッシュを自動で更新してくれるので便利ですね。

###検知処理の高速化

例えばこんな機能を追加しようとして

* お店(shop)の評点を集計する
* 評点は全レビュー(review)の平均点を使用する

これをバッチ処理で開発する場合

* 差分更新だけにしたい
* 更新対象は、前回バッチ実行時から今まででreview.updated_atが更新されたかで検知したい

touchオプションを付けておくと、review作成・更新時にshopのupdated_atも自動更新してくれるので、バッチ処理ではshopのupdated_atを参照するだけで集計対象を検知できるようになります。
（もしreviewのupdated_atを参照しようとすると、shopとReviewは1:Nなので参照するレコードが多くなり処理が遅くなります）

##touchしたくない場合

touchオプションを付けたものの、なんらかの理由（子レコードを大量作成や、全て更新）でtouchしたくない場合、`ActiveRecord.no_touching` で一時的に無効にできます。

```ruby
shop = Shop.last

ActiveRecord::Base.transaction do
  ActiveRecord::Base.no_touching do
    shop.reviews.find_each do |review|
      # shopのupdated_atは更新されない
      review.update!(some_attributes)
    end
  end
end
```

##参考URL

https://railsguides.jp/association_basics.html#belongs-to%E3%81%AE%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3-touch
https://postd.cc/the-complete-guide-to-rails-caching/
https://techracho.bpsinc.jp/hachi8833/2018_04_18/55475
lメソッドで時刻の表示が指示通りできない

## 起きたこと
https://qiita.com/jnchito/items/831654253fb8a958ec25
に従い設定をしました。
しかし、ja.ymlのdefaultをいくらいじってもブラウザに指示通りの表記がされませんでした。

```ruby:ja.yml
ja:
 time:
   formats:
     default: "%Y/%m/%d"
```

## 結論
ja.ymlファイルの中に2つja:の塊を作っていたことが原因でした。
もう一つのja:の塊とは別のことも記述していました。具体的にはエラー時に表示されるカラム名を日本語に変換するためのデータです。

```ruby:ja.yml改善前
ja:
 time:
   formats:
     default: "%Y/%m/%d"
ja:     
 activerecord:
   attributes:
     user:
      nickname: 名前
      grade_id: 段位
      email: Email
      password: パスワード
      password_confirmation: 確認用パスワード
```

これを一つにまとめて、

```ruby:ja.yml改善後
ja:
 time:
   formats:
     default: "%Y/%m/%d"
 activerecord:
   attributes:
     user:
      nickname: 名前
      grade_id: 段位
      email: Email
      password: パスワード
      password_confirmation: 確認用パスワード
```

とすることで年/月/日の表示が無事できました。
インデントの幅がスペース一つずれていても認識されなかったので注意が必要です。

以上
PHP array_mapの色々活用方法

# 初めに

@tadsan さんに他の書き方教えていただいたので追記しています！
@tadsan さんありがとうございます！:bow:

比較
こんな時どうしよう、、、
こんな時どうしてたっけ?
みたいなことが10000億回ぐらいあるので、
ここに記録しておくことにしました！

記事は温かい目でみて頂けると嬉しいです！
優しい世界大事、大事ヽ(´▽｀)/

ちなみに、コード実際にすぐ動かしたいだ！という方に以下オススメです！
私はよくお世話になってます！『paiza』さんありがとうございます！
https://paiza.io/ja/projects/new


###in_array +  array_map

:thinking:配列の中のあるキーの値の中に含まれているか確認したいんだ~~~~の時に使用

コード例

```.PHP
<?php
$user_article_id = 454556;

$stars = [
    0 => ['id' => 123424, 'article_id' => 454545],
    1 => ['id' => 198989, 'article_id' => 454556],
    2 => ['id' => 132323, 'article_id' => 454547]
];

// article_idの配列作成
$articleIds = array_map(fn($el) => ($el['article_id']), $stars);

//『articleIds』に『user_article_id』が含まれているかの確認
if(in_array($user_article_id, $articleIds)){
    echo '含まれている';
}else{
    echo '含まれていない';
}
//含まれている

```

上記を『array_column』を使って書くと以下になります！
@tadsan さんに教えていただきました！

```.PHP
<?php
$user_article_id = 454556;

$stars = [
    0 => ['id' => 123424, 'article_id' => 454545],
    1 => ['id' => 198989, 'article_id' => 454556],
    2 => ['id' => 132323, 'article_id' => 454547]
];

// array($article_id => $id) 配列作成
$articleIds = array_column($stars, 'id', 'article_id');

//『articleIds』に『user_article_id』が含まれているかの確認
if (isset($articleIds[$user_article_id])){
    echo '含まれている';
} else {
    echo '含まれていない';
}
//含まれている
```


###array_map + count + array_sum

:thinking:配列の中のあるキーの値の配列の合計数を出したいのどうすれば良いかな？

```.PHP
<?php
$stars = [
    0 => ['ids' => [123424, 343434], 'article_id' => 454545],
    1 => ['ids' => [198989, 545454], 'article_id' => 454556],
    2 => ['ids' => [132323, 767676, 87878], 'article_id' => 454547]
];

// 各idsの配列の合計を格納した配列の作成
$idCounts = array_map(fn($el) => count($el['ids']), $stars);

//上記の配列数を足す
$star_id_total =  array_sum($idCounts);

echo $star_id_total; // => 7
```

上記を『array_reduce()』を使って書くと以下になります！
@tadsan さんに教えていただきました！

```.PHP
<?php
$stars = [
    0 => ['ids' => [123424, 343434], 'article_id' => 454545],
    1 => ['ids' => [198989, 545454], 'article_id' => 454556],
    2 => ['ids' => [132323, 767676, 87878], 'article_id' => 454547]
];

$star_id_total = array_reduce($stars, fn($sum, $el) => $sum + count($el['ids']));

var_dump($star_id_total); // => 7
```

ちなみにこれをforeachだけで書くとしたらのサンプルコード1

```.PHP
<?php
$stars = [
    0 => ['ids' => [123424, 343434], 'article_id' => 454545],
    1 => ['ids' => [198989, 545454], 'article_id' => 454556],
    2 => ['ids' => [132323, 767676, 87878], 'article_id' => 454547]
];
$count = 0;
foreach ($stars as $star){
    $ids = $star['ids'];
    foreach ($ids as $id){
        $count += 1;
    }
}
echo $count;  // => 7

```

ちなみにこれをforeachだけで書くとしたらのサンプルコード2

```.PHP
<?php
$stars = [
    0 => ['ids' => [123424, 343434], 'article_id' => 454545],
    1 => ['ids' => [198989, 545454], 'article_id' => 454556],
    2 => ['ids' => [132323, 767676, 87878], 'article_id' => 454547]
];
$count = 0;
foreach ($stars as $star){
    $idCount = count($star['ids']);
    $count += $idCount;
}
echo $count;  // => 7

```

#最後に
終わりです！
また少し凝ったやつあったら書き足していく予定です！
ちなみに私はこの書き方が絶対だという感じのものはないです。
Windows 10でSIPp 6.3.1を動かす

## Windows 10でSIPp 6.3.1を動かす

「makeできた」ことだけ報告します。make方法は別途紹介したいと思います。

```
C:\Users\SMorifuku>sipp -v

 SIPp v3.6.1-RTPSTREAM.

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License as
 published by the Free Software Foundation; either version 2 of
 the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public
 License along with this program; if not, write to the
 Free Software Foundation, Inc.,
 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

 Author: see source files.
```

### 経緯とか

* [ここ](https://qiita.com/BrianMegane/items/a53338e3c8884b2ed2a3)などでSIPp-3.5のmake方法が紹介されていますが、自分はエラーが多発し、うまく行きませんでした。
* 悔しいので、現時点（2020/11/22）の最新版のSIPp-3.6.1のmakeにチャレンジしました。
* なんとすんなりmakeできました。
* SIPp-3.6からcmakeでmakeしているので、makeしやすくなったのではないかと思います。
* Windows 10のCygwin64環境でmakeしています。
awaitって大事メモ

#つまったこと
if文で条件式の中で関数を読んで返ってきたステータスを基に判断することをした。

結果、どの条件にもはまらなかった。

なぜか？
非同期で関数を呼ばれたため、returnの値が来ない間に条件式が判断されたから。

変更前

```javascript
}else if(await getStatus(event.source.userId)==="2"){
```


変更後

```javascript

}else if(getStatus(event.source.userId)==="2"){
```


awaitとか書いて関数を呼び出すのがめんどいから、
その場で短く書けるようになったのかな。
Redmineのデフォルトテーマをちょこっといじってオリジナルテーマをサクッと作るのだ

#まずはデフォルトテーマを丸々コピーしてオリジナルテーマの基礎を作成
この記事は『/var/lib/redmine』にRedmineをインストールした前提ね。
まずは『/var/lib/redmine/public/themes』にテーマ名のフォルダーを作成。
今回はテーマ名『atai』にしたよー。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/21b76965-1de5-7f84-6a68-ea5658e74e44.png)
そしたら『/var/lib/redmine/public』内にある『images』『javascripts』『stypesheets』をさっき作った『atai』フォルダーにコピー。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/c2d2d271-add5-aac0-65a1-e407f87efdde.png)
あとは管理画面に行って…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/92f75671-6bdb-5bbf-7705-980dfb552c8c.png)
表示タブのテーマで設定すればOK！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/b6f13631-3bd5-ef38-0489-28da1da6162a.png)
ね？簡単でしょ？


#ブラウザのデベロッパーツール使って感触を確かめながらCSS調整
Chromeなら『Ctrl + Shift + i』でデベロッパーツール開くん！
んで、変更したい場所を選択、どのCSSファイルの何行目が適用されてるか分かるん！
右サイドバーのCSSの値は変更すればその場で反映されるん！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/359fe0dc-3877-19d8-cd5a-c0231d547b3a.png)
『application.cssの29行目のbackground-colorの値は#000000かな～』
てな感じで一つ一つパラメータを決めながら、元のCSSファイルを変更していくん！

#CSS変更しても反映されないんだけど！
ブラウザのキャッシュをクリアしてページを再読み込み！
Chromeなら『Ctrl + Shift + r』じゃ！


#いい感じの配色にするには？
~~まずカラーコーディネーターの資格を取ります。~~
[Color Scheme Designer](https://colorschemedesigner.com/csd-3.5/) 便利です！
ほぼほぼ説明不要なくらいインターフェースが直感的で分かりやすいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/cc8f1353-6279-045c-bfd6-28245f4495d7.png)
Color List タブで色のコードをコピれますん。
うーん、痒い所に手が届く！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/794fa321-306e-aa55-2f21-7e51987d424d.png)


#はい、こんな感じ
うーん、とっても使いやすくなったぞ^^
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/556b166a-a5b1-211f-8f0c-495f993c7417.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/f3dd5204-cea7-447c-f0e3-1d7aea6116d7.png)
画像は下記から頂きました。
[【公式】10話邪神ちゃんドロップキックのアニメ画像 - アル ](https://alu.jp/series/%E9%82%AA%E7%A5%9E%E3%81%A1%E3%82%83%E3%82%93%E3%83%89%E3%83%AD%E3%83%83%E3%83%97%E3%82%AD%E3%83%83%E3%82%AF/scene/nSmOPxK7AFDFJ0cKufeS)



#蛇足
デベロッパーツールで変更後のCSSをダウンロードできれば楽だな～。
CSSファイルを差し替えちゃえばデベロッパーツール上でやった編集が一気に反映される！

『期限が1日以内のチケットが5件以上あったらヘッダーに点滅するアイコン表示』
なんて実務的なカスタマイズしてもいいかもね。


#バージョン
CentOS Linux release 8.2.2004 (Core)
Redmine 4.0.6
GoToは最大限の警戒をもって使用します（原則禁止）

# GoToを禁止にされると困ること

**VB(A)**をお使いのみなさん、**GoTo使用禁止**で、困っていませんか。
GoToの使用を禁止にすると、

```OnError.bas
On Error Resume Next
```
とするしかなく、次のようなエラーチェックを**大量にコーディング**する必要があります。

```ErrHandling.bas
dim hasErr as Boolean
hasErr = False

If Not hasErr Then
    ' コーディング
end if
If Err.Number <> 0 Then
    hasErr = True
    ' 例外発生時の処理
End if
If Not hasErr Then
    ' コーディングの続き
end if
If Err.Number <> 0 Then
    hasErr = True
    ' 例外発生時の処理
End if
・
・
・
```
コードの可読性が低下し、不具合（バグ）を誘発しかねません。

# ベストプラクティス - VB(A)の例外処理
* GoTo文は原則禁止とします。
* ただし、イベントハンドラ等のSubプロシージャ内であれば、`On Error GoTo - Resume` の組み合わせで最大限の警戒をもって使用することを推奨します。

```snipet.bas
Sub button_Click()
On Error GoTo Travel
    
    ' ここにコーディングしてください。
    
Eat:
    ' 後処理があればここにコーディングしてください。
    ' (例外が発生しそうな場合は、 On Error Resume Next で、例外処理を行ってください。)
    Exit Sub
Travel:
    ' 例外発生時の処理があればここにコーディングしてください。
    ' ※ Errオブジェクトはシングルトンですので、別のサブルーチンや関数を呼び出すと、
    '    その中で、Errオブジェクトの内容が変化してしまうことがあります。
    MsgBox Err.Description, vbCritical, "予期せぬエラー [" & Err.Number & "]"
    Resume Eat
End Sub

```

# おわりに

これまで、ラベル名に、`ExitProc`や`ErrHandler`を使っていましたが、これからは、`Eat`や`Travel`を使うことを推奨します。

## Go To キャンペーン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/da95db0d-246e-dc77-8f9a-a4f978889783.png)
出典：[https://www.gfo-sc.jp/gototraveleat/](https://www.gfo-sc.jp/files/20201019/e41f337fc2aafa18ca4317e23694c3b467f91899.jpg)
docker inspect --format　メモ

（Qiitaの下書きに中途半端に残っていた。メモなので適宜更新）

--formatを使ってdocker inspectの好きな情報を取り出す。

### よく使うフォーマット（自分用）

```powershell
docker inspect --format "\
host:{{.Name}} \
ip: {{.NetworkSettings.IPAddress}} \
gw: {{.NetworkSettings.Gateway}} \
port [host]: {{.NetworkSettings.Ports}}" $(docker ps -q)
```

#### 結果

```
host:/container-name \
ip: 172.17.0.2 \
gw: 172.17.0.1 \
port [host]: map[10010/tcp:[] 22/tcp:[{0.0.0.0 12223}] 3000/tcp:[{0.0.0.0 3000}] 80/tcp:[]]
```


### IPだけ

```powershell
PS C:\Users\name> docker inspect $(docker ps -q) | jq -r '.[].NetworkSettings.Networks.bridge.IPAddress'
172.17.0.3
172.17.0.2
```

### IPと名前

```powershell
PS C:\Users\name> docker inspect $(docker ps -q) | jq -r '.[].Name, .[].NetworkSettings.Networks.bridge.IPAddress'
/api-test2
/api-test
172.17.0.3
172.17.0.2
```

### 整形して取る

```powershell
PS C:\Users\name> docker inspect $(docker ps -q) | jq -r '.[] | { Name: .Name, IP: .NetworkSettings.Networks.bridge.IPAddress }'
{
  "Name": "/api-test2",
  "IP": "172.17.0.3"
}
{
  "Name": "/api-test",
  "IP": "172.17.0.2"
}
```


### いろいろできるっぽい

```powershell
PS C:\Users\name> docker inspect $(docker ps -q) | jq '.[] | {moge: {hoge: { Name: .Name, IP: .NetworkSettings.Networks.bridge.IPAddress }}}'
{
  "moge": {
    "hoge": {
      "Name": "/api-test2",
      "IP": "172.17.0.3"
    }
  }
}
{
  "moge": {
    "hoge": {
      "Name": "/api-test",
      "IP": "172.17.0.2"
    }
  }
}
```
Pythonでthisを使う(バッド)プラクティス

概要
---
某OSSで見つけたテクニック。

```Python
bs = BookShelf('XX入門', '初めてのYY', '今さら聞けないZZ')
bs.map_(lambda: print(this))
```

```text:stdout
XX入門
初めてのYY
今さら聞けないZZ
```

唐突に出現した`this`。一体どこから生えてきたのか？

種明かし
---
コールバック呼び出し前に細工をしていた。

```Python
class Book:
    def __init__(self, name):
        self._name = name
        
    def __str__(self):
        return self._name

class BookShelf:
    def __init__(self, *book_names):
        self._books = [*map(Book, book_names)]
    
    def map_(self, callback):
        for book in self._books:
            callback.__globals__['this'] = book
            callback()
        
        del callback.__globals__['this']
```

分かってみれば大したこと無いが、
インタプリタやIDEの拡張を疑いしばらく悩みこんでしまった。

バッドプラクティスだと思う理由
---
次のように、引数として渡した方がPythonicだと思うから。

```Python
class BookShelf:
    def __init__(self, *book_names):
        self._books = [*map(Book, book_names)]
    
    def map_(self, callback):
        for book in self._books:
            callback(book)

bs = BookShelf('XX入門', '初めてのYY', '今さら聞けないZZ')
bs.map_(lambda this: print(this))
```

Zen of Python を大事にしたい。

> Explicit is better than implicit.
暗示するより明示するほうがいい。

**参考**： [Qiita - プログラマが持つべき心構え (The Zen of Python)](https://qiita.com/IshitaTakeshi/items/e4145921c8dbf7ba57ef)
GitとＣIの説明

#CI（継続的インテグレーション）の基本

共有しているリポジトリに統合するだけで、「ビルド」と「テスト」が自動的に実行される手法のことを言います。
Gitのリポジトリにコミットする

https://tracpath.com/bootcamp/ci/continuous-integration.html

有名なソフトウェア
サークルCI、ジェンキンス

【Java版】CI（継続的インテグレーション）ツール導入ガイド

https://tracpath.com/bootcamp/ci/


#Git

コンクリフトがおきた時の対処方法
git reset --merge

チーム開発を行う際には
全員にGITのIDを作成してもらう、
レポジトリを作成するA　各チームにAのクローンを作成してもらう
各自ローカルレポジトリを作成してもらい、クローンを入れる。

変更を行ったら、ステージ、コミットでローカルでコミットを行い
レポジトリにプッシュする、まちがえてしまったりしたら本体のプルすること

プルした際にコンクリフトが発生したら、適時判断してどちらを優先させるか
判断する事。

プッシュした際にコンクリが発生したら、１度プルしてから
プッシュした方が良い。


別々で作成する場合には、ブランチを作成する。
マスターにマージしたいときには、ブランチのマージを作成して
プルリクエストを投げて、管理者にマージの依頼をする。


新規の場合には、新規フォルダを作成してから
クローンを作成する、そこからGITHUBと連携を取る
現場で使えるTSVの任意の値だけ比較(perl編)

ある2つのTSVのある列の値が同じ行を出力する

```
%hash = ();
open(DATAFILE, "< a.tsv") or die("error :$!");

while (<DATAFILE>){
  chomp;
  @c=split/\t/;
  $hash{$c[3]}=$_; # 4個目の値をキーとして行を格納する
}

close(DATAFILE);

open(DATAFILE, "< b.tsv") or die("error :$!");

while(<DATAFILE>) {
  chomp;
  @c=split/\t/;
  if (exists $hash{$c[3]}) { # 4個目の値をキーとして探す
    print $_."\n";
  }
}

close(DATAFILE);

```
深層強化学習2　強化学習の実装

[Aidemy](https://aidemy.net/)　2020/11/22
#はじめに
　こんにちは、んがょぺです！バリバリの文系ですが、AIの可能性に興味を持ったのがきっかけで、AI特化型スクール「Aidemy」に通い、勉強しています。ここで得られた知識を皆さんと共有したいと思い、Qiitaでまとめています。以前のまとめ記事も多くの方に読んでいただけてとても嬉しいです。ありがとうございます！
　今回は、深層強化学習の2つ目の投稿になります。どうぞよろしくお願いします。

＊本記事は「Aidemy」での学習内容を「自分の言葉で」まとめたものになります。表現の間違いや勘違いを含む可能性があります。ご了承ください。

今回学ぶこと
・強化学習の実装

#強化学習の実装
##環境作成
・「強化学習」のChapterでは、環境などを自分で定義していたが、今回は強化学習用のさまざまな環境を用意しているライブラリを使用して環境などを作成していく。
・使用するライブラリは__「keras-rl」__というもので、これは__Keras__と__OpenAIGym（Gym）__というライブラリで構成される。今回はこれを使って__カートポールのデモ__を__DQN__で学習する。

・まずは__環境__を作成する。方法は__「env=gym.make()」__とするだけで良い。引数には環境の種類を指定する。カートポールの環境は__「"CartPole-v0"」__と指定する。以降はenvインスタンスにアクセスすることで操作できる。
・今回のカートポールでは、行動は__「カートを右に移動させる」「カートを左に移動させる」__の2つであり、これを取得するには__「env.action_space.n」__とすれば良い。

・コード![スクリーンショット 2020-11-19 10.31.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698700/d10ad3fb-5063-56c5-aaf1-453352008e27.png)


##モデルの構築
・環境を作成したら、Kerasの関数を使って__多層ニューラルネットワークを構築する__。モデルはSequentialモデルで構築する。次に、__Flatten()__で多次元の入力を一次元に変換する。入力の形「input_shape」には、カートポールの現在の状態を指定するため、__「env.observation_space.shape」__を使う。
・層の追加は__「model.add()」__で行えば良い。全結合層はDense、活性化関数の指定はActivation()で行う。引数には「relu」「linear」などを指定する。

・コード![スクリーンショット 2020-11-19 10.32.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698700/a8af8cb2-4c1f-3956-62f8-26e9086e06ff.png)


##エージェントの設定1　履歴と方策
・ここでは強化学習の本体である__エージェントの設定__を行う。まずは、この設定に必要な__履歴__と__方策__を設定する。(履歴はそのまま「過去にどのような行動をしたかの履歴」)
・__履歴__は__「SequentialMemory(limit,window_length)」__で設定できる。__limit__は記憶しておくメモリの数である。
・__方策__については、ボルツマン方策をとる時には__「BoltzmannQPolicy()」__を使い、ε-greedy手法をとる時には__「EpsGreedyQPolicy()」__を使う。

・コード![スクリーンショット 2020-11-19 10.41.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698700/b834e4f7-d691-531d-e28c-98eda7808306.png)

##エージェントの設定2
・前項の履歴と方策を使って、エージェントを設定する。DQNアルゴリズムが実装されている__「DQNAgent()」__を呼び出し、以下の引数を与えれば良い。
・引数には、モデル__「model」__、履歴__「memory」__、方策__「policy」__、行動数__「nb_actions」__、初めの何ステップを強化学習に使わないのかを指定する__「nb_steps_warmup」__を設定する。
・上記を「dqn」という変数に入れたとすると、__「dqn.compile()」__でエージェントの学習方法を指定する。第一引数としては__最適化関数__を指定し、第二引数としては__metrics__で表される評価関数を指定できる。

・コード（modelなどは前項のものを使用）![スクリーンショット 2020-11-19 11.12.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698700/ff94997e-3e16-3d04-961d-1f9fd389a025.png)


##テストの実施
・前項のdqnエージェントを学習させるには__「dqn.fit()」__を使えば良い。引数としては、__環境__（コード上ではenv）、エピソード数__「nb_steps」__、可視化するかどうか__「visualize」__、ログを出力するかどうか__「verbose」__がある。
・エージェントに学習させたら、これを__テスト__する。テストは、エージェントを実行し、実際どのぐらいの報酬が得られるかを評価する。これは__「dqn.test()」__で行える。引数は「dqn.fit()」と同じだが、エピソード数のみ__「nb_episodes」__とする。

#まとめ
・ライブラリを使用して強化学習を行うときは、__keras-rl__を使う。
・__「gym.make()」__で環境を作成したら、モデルを作成して層を追加していく。また、__履歴__と__方策__を設定し、これらを使ってエージェントも作成する。
・作成したdqnエージェントを__「dqn.fit()」__で学習させ、__「dqn.test()」__でテストする。

今回は以上です。ここまで読んでくださり、ありがとうございました。
「レガシーコードからの脱却」読書メモ その4

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

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

---
第Ⅱ部　ソフトウェアの寿命を延ばし価値を高める9つのプラクティス
　10章　プラクティス6 まずテストを書く
　11章　プラクティス7 テストでふるまいを明示する
　12章　プラクティス8 設計は最後に行う
を読んだメモ

---
# プラクティス6 まずテストを書く

---
# 「テスト駆動は死んだ」
TDD is dead, Long live testing.
https://dhh.dk/2014/tdd-is-dead-long-live-testing.html

---
# テストではなく仕様である
受け入れテスト、QAテストの代用にはならない。
QAテストの観点で「テスト駆動開発」をするとテストが重すぎる。

---
# テスト駆動開発の目的を見失うと失敗する

---
# テスト駆動開発の目的
・「作るものは何か」を明確にしテストしやすいコードを書く。
・頻繁なフィードバックを得る。
・リファクタリングをしやすくする。
→テストはふるまいの仕様であり、回帰テストである。

---
# テストもソースコード
テストも「CLEAN」を保つ。
→テストが開発のブレーキとなるのを防ぐ必要がある。

---
# プラクティス7 テストでふるまいを明示する

---
# テストではなく仕様である(2回目)
テストは実行可能な生きた仕様。
ドキュメントに書かれた仕様が実装と一致していることを確認するのは困難。

---
# カバレッジを100%にする
テストは仕様であり、仕様と実装は対応する。
仕様にないパスは実装すべきではない。
→コードが複雑になるのを防ぐためのテスト駆動開発。

---
# バグはテストの不足
バグを再現させるテストを書いてから修正する。
→バグを修正するだけでなく、プロセスを改善するきっかけにする。

---
# プラクティス8 設計は最後に行う

---
注意
ここでの「設計」とは、コードとテストができている状態から、保守性を維持するための設計活動。
※**すべて**の設計を最後まで先延ばしにするわけではない。

---
> テストを最初に書いて、最後に設計をしよう。

---
# テスト駆動開発は設計方法論
テストがあることで安全にコードをクリーンアップできる。
開発の中で学んだことを設計に反映する。
→開発中の課題から手がかりが出てくる。

---
# コードは読むためのもの
読みやすいコードは保守しやすい。
「何をやるか」をプログラミングする。「どうやってやるか」はオブジェクトの中にカプセル化する。

---
# つづく
Flutter入門メモ


FlutterはAndroidアプリとiPhoneアプリを同時に開発できるライブラリ

1. インストール方法
    2. https://flutter.dev/docs/get-started/install

特徴
- マテリアルデザインを簡単に組むことができる

iPhoneのシュミレーター起動

```bash
$ open -a Simulator
```

下記を実行することで、chrome上でもシュミレーションしながら開発ができるようになります

```bash
$ flutter channel beta
$ flutter upgrade
$ flutter config --enable-web
```

### 新規アプリ作成

```bash
$ flutter create myapp
```

### アプリ起動

```bash
$ flutter run
```


```bash
$ flutter run 
Multiple devices found:
Web Server (web) • web-server • web-javascript • Flutter Tools
Chrome (web)     • chrome     • web-javascript • Google Chrome 86.0.4240.198
[0]: Web Server (web-server)
[1]: Chrome (chrome)
Please choose one (To quit, press "q/Q"): 0
Running "flutter pub get" in ibank...                              295ms
Launching lib/main.dart on Web Server in debug mode...
Syncing files to device Web Server...                              13.9s
lib/main.dart is being served at http://localhost:52171
The web-server device requires the Dart Debug Chrome extension for debugging. Consider using the Chrome or Edge devices for an improved development workflow.

Warning: Flutter's support for web development is not stable yet and hasn't
been thoroughly tested in production environments.
For more information see https://flutter.dev/web

🔥  To hot restart changes while running, press "r" or "R".
```
現場で使えるゴルーチン(並列制御)


```
func main() {
	ch := make(chan struct{}, 10)
	var wg sync.WaitGroup
	for i := 0; i < 1000; i++ {
		ch <- struct{}{}
		wg.Add(1)
		go func(i int) {
			defer func() {
				<-ch
				wg.Done()
			}()

			fmt.Println(i)
		}(i)
	}
	wg.Wait()
}
```
https://play.golang.org/p/Cry94fFpeFH
LINE Messaging APIで文末に絵文字を入れるメモ

テキストの長さをとってそれをindexとしておく。

```javascript
                
var pushText = "hogehoge";
// 文末に絵文字を入れるための準備
let textLength = pushText.length;
pushText += "$";

// メッセージ配列の初期化
let messageList = [];

// メッセージの作成
messageList = [{
  "type": "text",
  "text": pushText,
  "emojis": [
   {
    "index": textLength,
    "productId": "5ac1bfd5040ab15980c9b435",
    "emojiId": "005"
   }
 ]
},{
  "type": "sticker",
  "packageId": "11537",
  "stickerId": "52002755"
}];
```