OmniAICreator/Qiita-1.07M huggingface dataset:
[GitHub Actions] 鬼の爆速実装！！！pytestのcoverageをPull Requestに表示させる

## この記事を読めばできるようになること
GitHub ActionsでpytestのcoverageをPRに表示させることができる
## 説明しないこと
- GitHub Actionsとは何か
- ymlファイルの記述方法

## 注意事項
これから紹介するソースはdockerを利用している

## 該当のyamlファイル
```.github/workflows/coverage.yml
# タイミングを指定
on:
  pull_request:

permissions: write-all

jobs:
  pytest_coverage:
    runs-on: ubuntu-latest

    steps:
      # リポジトリをチェックアウト
      - name: Checkout
        uses: actions/checkout@v2

      - name: generate .env
        run: chmod +x set-up-env.action.sh && sh set-up-env.action.sh
        env:
          ENVIRONMENT_VARIABLE1: ${{ secrets.ENVIRONMENT_VARIABLE1 }}
          ENVIRONMENT_VARIABLE2: ${{ secrets.ENVIRONMENT_VARIABLE2 }}

      - name: Run Tests
        run: |
          docker-compose build
          docker-compose up -d
          docker-compose run app pytest --cov --cov-branch --cov-report=term-missing --junitxml=pytest.xml test | tee pytest-coverage.txt

      # テスト結果をプルリクにコメントする
      - name: Pytest coverage comment
        uses: MishaKav/pytest-coverage-comment@main
        with:
          pytest-coverage-path: ./pytest-coverage.txt
          junitxml-path: ./pytest.xml
```

## コマンド説明
###   Run Testsコマンド
```coverage.yml
 - name: Run Tests
   run: |
     docker-compose build
     docker-compose up -d
     docker-compose run app pytest --cov --cov-branch --cov-report=term-missing --junitxml=pytest.xml test | tee pytest-coverage.txt
```

#### docker-compose run app pytest --cov --cov-branch --cov-report=term-missing --junitxml=pytest.xml test | tee pytest-coverage.txtについて
 - `docker-compose run app`とすることでコンテナ内でコマンドを実行することが可能
 - `--cov`でテスト結果のcoverageを表示させることが可能
 - `--cov-branch`で条件分岐の網羅テスト率(C1カバレッジ)を見ることが可能
 - `--cov-report=term-missing`でコマンドラインで網羅できなかったコード行番号を表示させることが可能
 - `--junitxml=pytest.xml`でXUnit形式のテストレポートを指定したファイルに出力可能
 - `tee pytest-coverage.txt`で標準入力から受け取った内容をファイルに書き出すことが可能
 - 結果的に`pytest.xml`と`coverage.txt`が新たに追加される
 
### Pytest coverage comment
```coverage.yml
 - name: Pytest coverage comment
   uses: MishaKav/pytest-coverage-comment@main
   with:
     pytest-coverage-path: ./pytest-coverage.txt
     junitxml-path: ./pytest.xml
```
- [pytest-coverage-comment](https://github.com/marketplace/actions/pytest-coverage-comment)よりそのまま引用
- このアクションを GitHub のワークフローに追加すると、Ubuntu 用のランナー (runs-on: ubuntu-latest など) が作成できる
- うまく行けば↓PRにこのように表示される
<img width="768" alt="スクリーンショット 2022-10-24 9.28.58.png (91.7 kB)" src="https://img.esa.io/uploads/production/attachments/14274/2022/10/24/126296/39586aa2-e50a-4317-a872-df1e60242b9a.png">

## Badge Colors
カバレッジ率によってバッジの色も変化する
<img width="254" alt="スクリーンショット 2022-10-24 9.30.09.png (28.9 kB)" src="https://img.esa.io/uploads/production/attachments/14274/2022/10/24/126296/6d9a0888-30bb-4816-b587-df2b534d2c4b.png">

## 参考にさせていただきました
- [GitHub Actions で Python アプリの自動テストを設定する](https://note.com/rescuenow_hr/n/n6cc083aa6374)
- [pytest-cov-4.0.0 Reporting](https://pytest-cov.readthedocs.io/en/latest/reporting.html)
- [pytest-coverage-comment](https://github.com/marketplace/actions/pytest-coverage-comment)

##### この記事がどなたかの手助けになっていれば幸いです。
【Rails】バリデーションのカスタムコンテキストon:を複数同時に指定したい場合の方法と仕組み

Railsでは、`on:`を使うことで、バリデーション実行タイミングを指定できたり、カスタムコンテキストとして実行するかしないかを調整できます。

https://railsguides.jp/active_record_validations.html#on

`on:`で定義したカスタムコンテキストを`valid?`等の引数に渡すことでバリデーションのチェックができます。
Railsガイドでは`valid?(:xxx)`の使い方が載っていますが、一度にカスタムコンテキストを複数指定する方法を書いておきたいと思います。

## 結論

結論としては、配列で指定してあげれば良いです。

```ruby:controller
def create
  book.valid?([:xxx, :yyy])
  ...
end
```

```ruby:book.rb
with_options on: :xxx do
  validates :title, presence: true
  ...略
end

with_options on: :yyy do
  validates :content, presence: true
  ...略
end

```

こうすることで、`:xxx`と`:yyy`どちらのバリデーションチェックもかけることができます。

## 疑問に思ったこと

配列で指定できるのは良かったのですが、
「なんで配列でも機能するし、シンボルを１つ渡しただけでも機能するんだろう？」と思いました。
なので、ソースコードを除いてみることにしました。

## Rails内の仕組み

初級者のため読むのにかなり苦労しました。ざっくりしかわかっていない点はご容赦ください、、、

1.まず、`valid?`メソッドの中で`self.validation_context`に、引数をそのまま渡しています。（上記の例だと`[:xxx, :yyy]`）

```ruby:gems/activemodel-6.0.6/lib/active_model/validations.rb 333行目あたり
def valid?(context = nil)
  current_context, self.validation_context = validation_context, context
  errors.clear
  run_validations!
ensure
...略
```

2.そして、以下ところで定義されているオプション（`options[:on]`）と先ほど代入した`validation_context`で一致するものがあるかどうかを調べていました。

```ruby:gems/activemodel-6.0.6/lib/active_model/validations.rb 152行目あたり

def validate(*args, &block)
  ...略
      options[:if].unshift ->(o) {
        !(options[:on] & Array(o.validation_context)).empty? # ①
      }
    end
  ...略
end

```

つまり、、、
`Array(o.validation_context)`として配列の形にしてから処理をしているので、`[:xxx, :yyy]`のような配列であっても、`:xxx`のように単にシンボルであっても処理ができるということがわかって、腑に落ちました。

方法としてはシンプルですが、この方法は自分のコーディングにも活かせそうだなと思いました。

## ちなみに

ちなみに上記のコードを読んでいる中ですごくRubyの勉強になった点がありました。

```ruby:gems/activesupport-6.0.6/lib/active_support/callbacks.rb 425行目あたり
def make_lambda
  lambda do |target, value, &block|
    target, block, method, *arguments = expand(target, value, block)
    target.send(method, *arguments, &block)
       # target => #<Book id: nil, title: "", content: "", created_at: nil, updated_at: nil>
       # method => :instance_exec
       # arguments => [#<Book id: nil, title: "", content: "", created_at: nil, updated_at: nil>]
       # block => #<Proc:.../lib/active_model/validations.rb:166 (lambda)> ⇦上記コード①のオブジェクト
  end
end
```

ここの`target.send(method, *arguments, &block)`でおこなっている事についてです。
各変数に入っている値がコメントアウトで示した場合、ここで行われているのは、
`send`メソッドで`instance_exec`メソッドが、引数を`arguments`を展開したBookオブジェクトとして呼ばれ、①のブロックのオブジェクトが実行される、というものでした。

つまり、ここでは①のブロックが、Bookオブジェクトを引数oとして実行されている、ということになりそうです。

## 最後に

今までは配列にすれば複数指定できる、OK!として終わってしまっていたところを、完全に理解できなかったとはいえ、ソースコードを追うところまでやってみたのは良かったかなと思います。

「ちなみに」で書いた部分については、`send`メソッドの理解、`instance_exec`というメソッドの存在と理解、`lambda`の理解が足りていなかった私にとっては読み解くのが難しく、頭が痛くなりそうでしたが、これを機に身をもって理解できて良かったと思いました。
SwiftでProtocolの配列をプロパティに持つオブジェクトをJSONにencodeする

# 概要
タイトルの通り、以下のようなJSONをencodeしようとしてハマったため、こちらの記事に簡単にメモしておきます。

```
{
    "value": 5,
    "list": [
        {
            "className": "A"
        },
        {
            "className": "B"
        }
    ]
}
```

実装例。containerをネストさせます。

```swift
import Foundation

protocol P : Encodable {}

class A : P {
    var className = "A"
}

class B : P {
    var className = "B"
}

class Data : Encodable {

    var value: Int = 5
    
    var list: Array<P> = [A(), B()]

    public func encode(to encoder: Encoder) throws {
        var rootContainer = encoder.container(keyedBy: CodingKeys.self)
        try rootContainer.encode(value, forKey: .value)

        var listContainer = rootContainer.nestedUnkeyedContainer(forKey: .list)
        for p in list {
            try listContainer.encode(p)
        }
    }

    enum CodingKeys: String, CodingKey {
        case value
        case list
    }
}


let data = try JSONEncoder().encode(Data())
print(String(data: data, encoding: .utf8)!)
// -> {"value":5,"list":[{"className":"A"},{"className":"B"}]}
```

検索用 エラーの例
```
error: type 'any P' cannot conform to 'Encodable'
        try rootContainer.encode(list, forKey: .list)

note: only concrete types such as structs, enums and classes can conform to protocols
        try rootContainer.encode(list, forKey: .list)

note: requirement from conditional conformance of 'Array<any P>' to 'Encodable'
        try rootContainer.encode(list, forKey: .list)
```
なでしこで100個の連番フォルダを一瞬で作る

先日、Pythonで[100個の連番フォルダを一瞬で作る方法](https://news.mynavi.jp/techplus/article/zeropython-95/)を紹介しました。
好評でしたので、なでしこ版を紹介します。

プログラムを実行するには、[なでしこ3のPC版](https://nadesi.com/doc3/go.php?16414)を利用してください。

```
100回、「doc{回数を3でゼロ埋め}」のフォルダ作成。
```

ターミナル(PowerShellやターミナル.app)を起動します。そして、「cnako3 -l」を実行します。そして、上記のプログラムを入力して[Enter]キーを2回押します。

![スクリーンショット 2022-11-17 21.56.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33180/b64ebb03-1026-6d35-a429-31a7901f2ff4.png)

そうです！
なでしこ超便利。自画自賛ですみません(*^▽^*)
.chm(compiled html help file)を Linux(Ubuntu)で開きたいメモ

漢には chm ヘルプファイルを見ねばならぬときもある...

chm を見るツールは需要もないのかあんまりなくて, あっても古いのが多いです.

## kchmviewer

![Screenshot from 2022-11-17 21-35-18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36275/3ff57f67-92ba-a15b-d7a5-b07dad5480d2.png)

現状(2022/11)のおすすめ.
KDE 環境では標準で使えるようです. qt webkit で描画しているので, レイアウトも大体うまく行きます

index やヘルプファイル全体の検索もできます.

Ubuntu だと apt では入らないので, ソースコードからビルドが必要です.

## xchm

https://github.com/rzvncj/xCHM

X11 なアプリです. とりあえず Ubuntu で apt で入ります.
index やヘルプファイル全体に渡っての検索も対応していますが,
CSS 等対応していないのか, レイアウトが崩れやすいです.

## Wine

https://help.k15t.com/scroll-chm-exporter/installing-microsoft-html-workshop-under-wine-93290645.html

htmlhelp.exe を wine で動かせば見れるっぽ? (未検証)

wine に標準搭載されている(?) hh.exe だと古い形式のヘルプファイルしか見れません. 

## ファイル展開

中身は html なので, extract_chmLib (apt で chmlib-bin で入る)で展開も手でしょうか.
コマンドラインで grep あたりでテキスト検索でもよい人向け
Rails 【where】日付・時間を範囲指定する際の注意点

## 行いたいこと
- where句を使用し、モデルのdeadline_onカラムから期日が近いデータを取り出したい。

## 完成形のコード
```
model.where(deadline_on: Date.today..Time.now.end_of_day + (2.days))
```

## 元々書いていたコード
```
model.where(deadline_on: Time.now.end_of_day + (2.days)..Date.today)
```
## 沼ったポイント
- 上記の元々書いていたコードでirb上でSQL文を確認していた際、BETWEEN節があったため問題ないと考えていた。
- 実際には、完成形のコードのように日時が早いものを先に後のものを後ろに記載しないと○日~○日までというような範囲指定はされないので注意が必要。
&&、||、!

### 「&&」

「&&」は複数の条件を1つにまとめる論理演算子で
日本語で言うところの「かつ」である。
2つ以上の条件式がどちらもtrueの時、全体もtrueになる。

`$x`&thinsp;\=&thinsp;10;
if(\$x&thinsp;\>5\&\&`$`x&thinsp;\<20)``&thinsp;\{
&emsp;&emsp;&thinsp;echo&thinsp;\$xは5より大きい、かつ20より小さい';
\}

→if文の条件式が共にtrueであったため、
 &thinsp;`$`xは5より大きい、かつ30より小さいが命令される。
&thinsp;&thinsp;よって$xは5より大きい、かつ20より小さいが出力される。

### 「||」

「||」は複数の条件を1つにまとめる論理演算子で
日本語で言うところの「または」である。
2つ以上の条件式がどちらもtrueの時、または片方でもtrueの時
全体もtrueになる。

`$x`&thinsp;\=&thinsp;10;
if(\$x&thinsp;\>5\|\|`$`x&thinsp;\>20)``&thinsp;\{
&emsp;&emsp;&thinsp;echo&thinsp;'\$xは5より大きい、かつ20より小さい';
\}

→if文の条件式のうち、`$`x&thinsp;>5がtrueであったため、
 &thinsp;`$x`は5より大きい、かつ20より小さいが命令される。
&thinsp;&thinsp;よって\$xは5より大きい、かつ20より小さい';が出力される。

### 「!」

「!」は条件を否定する論理演算子である。
式がtrueであればfalseに、式がfalseであればtrueになる。

`$x`&thinsp;\=&thinsp;10;
if(!($x&thinsp;\=\=&thinsp;20\)\)&thinsp;\{
&emsp;&emsp;&thinsp;echo&thinsp;'`$`xは20である';
}

→if文の条件式である\\$x == 20はfalseであるが、
&thinsp;&thinsp;&thinsp;論理演算子!が定義されているためtrueになり
&thinsp;&thinsp;&thinsp;\$xは20であると表示される。
【Ruby】Setクラス(集合)の扱い方

本記事ではSetクラスの性質や使い方について記述します。

## Setオブジェクトを作成

Setオブジェクトを作成するには、`Enumerable`モジュールの`#to_set`を呼ぶか`Set.new`を使用します。

`Set.new`で渡せる引数は`Enumerable`です。

### 空のSetオブジェクトを作成する
Setオブジェクトを生成するには、`Set.new()`を使用します。

```ruby
> s = Set.new
=> #<Set: {}>
```

### 配列からSetオブジェクトを作成する
配列のような`Enumerable`なオブジェクトを `Set.new()`に渡してSetオブジェクトを生成することができます。 この際、重複した要素は削除されます。

```ruby
> s2 = Set.new([1, 3, 5, 5])
=> #<Set: {1, 3, 5}>
> s2 = Set.new(1..3)
=> #<Set: {1, 2, 3}>
```

`Enumerable`には `to_set()`メソッドが用意されているので、これを使用してSetオブジェクトを生成することもできます。

```ruby
> s3 = ['foo','bar'].to_set
=> #<Set: {"foo", "bar"}>
```

## 要素を追加する

Setオブジェクトに要素を追加するには`add`メソッド、または `<<`演算子を使用します。
`add?`メソッドを使用した場合、重複した要素があるときの返り値が`nil`になります。

```ruby
> s4.add(1)
=> #<Set: {1}>
> s4 << 2
=> #<Set: {1, 2}>
> s4.add(2)
=> #<Set: {1, 2}>
> s4.add?(2)
=> nil
```

一度に複数の要素を追加したい場合、`merge`メソッドを使用ます。

```ruby
> s4.merge([3, 4, 5])
=> #<Set: {1, 2, 3, 4, 5}>
```

## 要素を削除する

Setオブジェクトにから1つの要素を取り除くには、`delete`メソッドを使用します。 
`delete?`メソッドを使用した場合、引数に指定した要素がないときの返り値が`nil`になります。

```ruby
> s4.delete(1)
=> #<Set: {2, 3, 4, 5}>
> s4.delete(2)
=> #<Set: {3, 4, 5}>
> s4.delete(2)
=> #<Set: {3, 4, 5}>
> s4.delete?(2)
=> nil
```

一度に複数の要素を取り除くには、`subtract`メソッドを使用します。

```ruby
> s4.subtract([3, 4])
=> #<Set: {5}>
```


## 集合にある値が含まれているか

`Set#include?`は指定した値がそのSetオブジェクトに含まれている場合に`true`を返します。

```ruby
> s = Set.new(%w(hoge foo bar))
=> #<Set: {"hoge", "foo", "bar"}>
> s.include?('hoge')
=> true
> s.include?('piyo')
=> false
```

`Set#subset?`または`<=`演算子を使用すると、あるSetオブジェクトの要素が、もう一方のSetオブジェクトにすべて含まれているかどうかを調べることができます。

```ruby
irb(main):021:0> s1 = Set.new([1, 2, 3])
=> #<Set: {1, 2, 3}>
irb(main):022:0> s2 = Set.new([2, 3])
=> #<Set: {2, 3}>
irb(main):023:0> s2.subset?(s1)
=> true
irb(main):024:0> s2 <= (s1)
=> true
irb(main):025:0> s1.subset?(s2)
=> false
irb(main):026:0> s1 <= (s2)
=> false
```

## 集合の演算

### 和集合
`+`演算子、または`|`演算子、`union`メソッドを使用することで、Setオブジェクト同士の和集合を求めることができます。

```ruby
> s1 = Set.new([1, 2, 3])
=> #<Set: {1, 2, 3}>
> s2 = Set.new([3, 4, 5])
=> #<Set: {3, 4, 5}>
> s1 + s2
=> #<Set: {1, 2, 3, 4, 5}>
> s1 | s2
=> #<Set: {1, 2, 3, 4, 5}>
> s1.union(s2)
=> #<Set: {1, 2, 3, 4, 5}>
```

### 積集合
`&`演算子を使用することで、Setオブジェクト同士の積集合を求めることができます。

```ruby
> s1 & s2
=> #<Set: {3}>
```

### 排他的論理和
`^`演算子を使用することで、いずれかのSetオブジェクトにしか含まれていない要素を調べることができます。

```ruby
> s1 ^ s2
=> #<Set: {4, 5, 1, 2}>
```

### 差集合
`-`演算子、または`difference`メソッドを使用することで、左辺に指定したSetオブジェクトにしか存在しない要素を調べることができます。

```ruby
> s1 - s2
=> #<Set: {1, 2}>
> s2.difference(s1)
=> #<Set: {4, 5}>
```

## 参考

https://docs.ruby-lang.org/ja/latest/class/Set.html

https://zenn.dev/yukito0616/articles/82d69a322cd4a0
#8 Bootstrapの各機能まとめ1

# #8 Bootstrapの各機能まとめ1
Bootstrapを機能毎にまとめて行きます。
今回は第一弾として**Background**、**Visually hidden**、**Form controls**の3つをまとめて行きます。

## 1. Background
https://getbootstrap.jp/docs/5.0/utilities/background/

### 1. bg-
bg-XXXX と指定することで背景色を変更できます。例. bg-primary：青背景
```html:html
<div class="bg-primary"></div>
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884987/72eda3d8-444a-0476-bddc-343d02a57d1f.png)


### 2. bg-gradient 
bg-gradientを以下のようにHTML、CSSファイルに追加することにより、線形グラデーションが背景画像として背景に追加されます
```html:html
<div class="bg-primary bg-gradient"></div>
```
```css:css
.bg-gradient {
    background-image: var(--bs-gradient)!important;
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884987/cd207040-427b-4767-5935-cc4a3a2d26ea.png)
※ 分かりづらいですが変わっています

## 2. Visually hidden
https://getbootstrap.jp/docs/5.0/helpers/visually-hidden/

### 1. visually-hidden, visulally-hidden-focusable
visually-hiddenは要素を視覚的に隠すことができます。補助技術 (画像読み上げソフトウェア) などに用いられる
visually-hidden-focusableはデフォルトでは要素を視覚的に非表示にすることができるが、フォーカスされたときに表示できる
```html:html
<div class="visually-hidden">ここの内容が消える</div>
<div class="visually-hidden-focusable">ここの内容が消える</div>
```
```css:css
.visually-hidden-title {
  @include visually-hidden;
}

.skip-navigation {
  @include visually-hidden-focusable;
}
```
## 3. Form controls

https://getbootstrap.jp/docs/5.0/forms/form-control/#file-input
### 1. form-control
＜input＞や＜textarea＞に、カスタムスタイル、サイズ調整、フォーカス状態などを自動で設定する
また、末尾に-lg, -smを付けることで高さを調節することができる。
```html:html
<input type="text" class="form-control">
<input type="text" class="form-control-lg">
<input type="text" class="form-control-sm">
```
### 2. disabled, readonly
disabled、readonlyという属性を追加することでinput, textareaへの書き込みができなくなる。この2つの違いとして、disabledはボックスの選択すらできなくなってしまうが、readonlyはボックスを選択することは可能

```html:html
<input type="text" class="form-control" disabled>
<input type="text" class="form-control" readonly>
```
### 3. File input
```html:html
<input class="form-control" type="file" id="formFile">
```
### 4. Detalists
データリストでは、＜input>＞の中から自動補完できる＜option>＞のグループを作成することができる。
```html:html
<input class="form-control" list="datalistOptions"">
<datalist id="datalistOptions">
  <option value="San Francisco">
  <option value="New York">
  <option value="Seattle">
  <option value="Los Angeles">
  <option value="Chicago">
</datalist>
```
[Java入門] コンソールアプリ用Scanner 備忘録

# コンソールアプリ用Scanner 備忘録
## 概要
Java入門者が作成するコンソールアプリにおいて、標準入力で操作する際に用いるScannerクラス。
サンプルコードを見様見真似で実装し、1度close()してしまうと、もう標準入力を受け付けません。

close()せず標準入力の度にScannerを作れば解決ではあるのですが、ちょっと格好悪い。
そこで、Scannerを管理するクラスを作り、毎回利用しましょう。

## 実装例
```java:ScannerManager.java
public class ScannerManager {
  /** スキャナーの宣言 */
  private Scanner stdin = null;
  /** スキャナーのインスタンス */
  public static ScannerManager instance = new ScannerManager();

  /** スキャナーのインスタンスを取得 */
  public static ScannerManager getInstance() {
    return instance;
  }
  /** Scannerを取得 */
  public Scanner getScanner() {
    return stdin;
  }
  /** 標準入力を開く */
  public void openScanner() {
    stdin = new Scanner(System.in);
  }
  /** 標準入力を閉じる */
  public void closeScanner() {
    if (stdin != null) {
      stdin.close();
    }
  }
  /** newできなくする */
  private ScannerManager() {
  }
}
```
Scannerクラスは上の通りです。Exception対応は各自やってください。
あとはメインの最初でOpenしてインスタンスを生成し、最後にCloseします。

```java:Main.java
public static void main(String[] args) {
    try {
      //Scannerを開く
      ScannerManager.getInstance().openScanner();
      //
      //好きに実装
      //
      //Scannerを閉じる
      ScannerManager.getInstance().closeScanner();

    } catch (IOException e) {
      System.out.println(e);
    }
  }
```
あとは標準入力を受け付けたいところで、ScannerManagerを呼ぶだけです。

```java
Scanner sc = ScannerManager.getInstance().getScanner();
String line = sc.nextLine();
```

## 最後に
ミス等ありましたら修正します。
Alibaba Container Registry(ACR)のはじめ方

# はじめに
ACRを使うに当たって、少し躓いたので備忘録として残しておきます。

### 1. ACRのパスワード作成
ACRのインスタンスメニューから「パスワードの設定」が行えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1667295/ca42a7aa-5c57-dd30-ec30-c49155384ecb.png)

### 2. ACRログイン
以下のコマンドを入力。パスワードを要求されたら、事前に作成したパスワードを入力します。
```shell
docker login --username=<username> <acr_instance_name>-registry.ap-northeast-1.cr.aliyuncs.com
```

### 3. イメージのビルドとプッシュ
```shell
# 1. DockerfileからビルドしてPushする場合
docker build <path/to/Dockerfile> -t <acr_instance_name>-registry.ap-northeast-1.cr.aliyuncs.com/<namespace>/<image_name>:<tag>
# 2. 既存のイメージのタグを変えてPushする場合
docker tag <image_id> <acr_instance_name>-registry.ap-northeast-1.cr.aliyuncs.com/<namespace>/<image_name>:<tag>
# Push
docker push <acr_instance_name>-registry.ap-northeast-1.cr.aliyuncs.com/<namespace>/<image_name>:<tag>
```
不要なインデックスを削除して、パフォーマンスをチューニング


__データベースを利用する時、効率的にクエリを処理する必要があります。__

今回は、MySQLを例に取り、
本の目次のようなインデックス、
本の本編のようなデータベースを例に取り、
パフォーマンスのチューニングを考えてみたいと思います。

最初に、__MySQL sys スキーマを読み解きます。__
<font color="Red">
MySQLデータベースの使用状況を把握するのに役立つビュー、関数、プロシジャーの集まりで、
使用状況を確認出来るようです。


__概要を確認しました。__
パフォーマンススキーマによって収集されたデータを解釈するのに役立つ一連のオブジェクトである。
sys スキーマオブジェクトは、チューニング、診断に使える。

①パフォーマンススキーマデータをわかりやすい形式に要約するビュー。
②パフォーマンススキーマの構成や診断レポートの生成などの操作を実行するストアドプロシージャー。
③パフォーマンススキーマ構成をクエリーして、フォーマットサービスを提供するストアドファンクション。
と、次のサイトに記載がありました。

https://dev.mysql.com/doc/refman/8.0/ja/sys-schema.html

<font color="Red">
<br>
⇒チューニングに使えるようです。
</font> 
<br>
<br>

__使用方法を確認しました。__
sys スキーマをデフォルトスキーマにすると、そのオブジェクトへの参照をスキーマ名で修飾する必要がなくなる。
```
mysql> USE sys;
Database changed
mysql> SELECT * FROM version;
+-------------+---------------+
| sys_version | mysql_version |
+-------------+---------------+
| 2.0.0       | 8.0.13-debug  |
+-------------+---------------+
```

host_summary_by_file_io ビューでは、ホスト別にグループ化されたファイル I/O が要約され、
ピコ秒からより読みやすい値 (単位付き) に変換された待機時間が表示される。

 ```
mysql> SELECT * FROM sys.host_summary_by_file_io;
+------------+-------+------------+
| host       | ios   | io_latency |
+------------+-------+------------+
| localhost  | 67570 | 5.38 s     |
| background |  3468 | 4.18 s     |
+------------+-------+------------+
```
と、次のサイトに記載がありました。

https://dev.mysql.com/doc/refman/8.0/ja/sys-schema-usage.html

<font color="Red">
<br>
⇒待機時間が確認出来るようです。
</font> 
<br>
<br>


__用途を確認しました。__
使われていないインデックス情報について確認し、削除。
```
select * from sys.schema_unused_indexes;
alter table 「object_name」 drop index 「index_name」;
```

__インデックスを削除する理由を整理しました。__

データベースでは、最初にインデックスという目次をみてから、効率的にデータベース本編を処理しようと試みます。
テーブルのレコードが更新(DELETE/INSERT/UPDATE)される場合、インデックスも更新されますよね。

<br>

<font color="Red">
書籍を例にとると、本の本編の内容変更があれば、目次が変わりますね。
でも、読まないページの目次が多いと、目次の効果が全く意味をなさなくなりますよね。。
目次がいっぱいで、目次を見てから必要な箇所だけ本を読もうとしたら、必要な箇所を読むスピードって、落ちますよね。</font> 

<br>
<br>
故に、インデックスの数が多ければ、その分更新するデータ量が増え、更新時のパフォーマンスが劣化します。
よって、目次であるインデックスを整理するとパフォーマンスがあがります。
<br>
<br>
データベースには、オプティマイザというのがあり、最適化しているようですが、
それでも、パフォーマンスチューニングしきれない所があり、こういった処理が有効となってくるケースがあるようです。
Pythonの割り算

割り算の演算子をしょっちゅう忘れるので備忘録を作りました。

# 通常の割り算

```python
# 8 ÷ 3 = 2.6666666666...
print(8 / 3)
```
答えは小数で表示される。

```python
# 4 ÷ 2 = 2.0
print(4 / 2)
```
このように割り切れる場合であっても答えは2.0と小数で表示される。

# 割り切れるタイプの割り算の答えを整数で表示する

intで変換することにより可能。

```python
# 4 ÷ 2 = 2
print(int(4 / 2))
```
round関数を使って丸めることも可能

```python
# 4 ÷ 2 = 2
n = round(4 / 2)
```

なお、割り切れない割り算をする際には、第二引数に数字を入れることで小数何桁まで値を求めるか指定することもできる。

ちなみにround関数は四捨五入ではないらしい(丸めようとしている数字が5の時の挙動が違う)。

# 割り算の商を求める

```python
# 商は2
print(8 // 3)
```

# 割り算の余りを求める

```python
# 余りは2
print(8 % 3)
```

# 参考文献

かわさきしんじ. "［解決！Python］割り算の商と余りを求めるには". 2022/08/09. https://atmarkit.itmedia.co.jp/ait/articles/2208/09/news036.html#:~:text=Python%E3%81%A7%E3%81%82%E3%82%8B%E5%80%A4%E3%82%92,%E3%81%9F%E5%95%86%E3%80%8D%E3%82%92%E8%A8%88%E7%AE%97%E3%81%99%E3%82%8B%E3%80%82, (2022/11/17).

ひろ. "Pythonの数値の桁数や丸めなどの操作のまとめ". HEADBOOST. 2021/05/06. https://www.headboost.jp/python-how-to-handle-digits/, (2022/11/17).
初学者のためのLiquid講座

# Liquidとは
Liquidとは、Shopifyが2006年に作ったオープンソースのテンプレート言語です。
アウトプット、ロジック、ループといったコンセプトがあり、変数（データ）を扱います。
ユーザー情報や商品情報など、ショップの動的なデータはLiquidの変数に格納されているため、Liquidを利用して表示の切り替えなどを行います。
今回は、Liquidの基本的な使い方と、実際の使用例を紹介したいと思います。

# 基本の使い方
## 出力
データの出力は、二重中括弧```{{}}```で囲います。
```
Hello {{name}}
Hello {{user.name}}
Hello {{ 'tobi' }}
```

## タグ
タグは、テンプレートのロジックと制御に使用されます。
中括弧にパーセント区切り```{% %}```で囲います。
```
{% comment %}
  これはコメントアウト
{% endcomment %}
```

# よく使うタグ
## comment
コメントアウトしたい箇所を、```{% comment %} 〜 {% endcomment %}```で囲います。
```
{% comment %}
  コメントアウト
{% endcomment %}
```
## assign
変数に値を割り当て。
先ほどの出力タグを使用することで、代入した値を出力できます。
```
{% assign name = '田中' %}
{{ name }}

# 「田中」が出力される
```
## if
条件がtrueの場合に実行。
```
{% if user != null %}
  こんにちは {{ user.name }}さん
{% endif %}
```
```else```や```elsif```を使った条件も可能。
```
{% if user.name == '田中' %}
  こんにちは　田中さん
{% elseif user.name == '鈴木' %}
  こんにちは　鈴木さん
{% else %}
  こんにちは みなさん
{% endif %}
```
## unless
if文の逆の意味。if文の演算子で```!=```を書いた時と同じ意味になります。
```
{% unless product.title == 'テストページ' %}
  こちらはテストページではありません
{% endunless %}
```
## case
ケース別の条件分岐。if文と似てますが、単純で数の多い条件に適してます。
```
{% case template %}
{% when 'label' %}
     このテンプレートは、ラベルです。
{% when 'product' %}
     このテンプレートは、プロダクトです。
{% else %}
     それ以外のテンプレート
{% endcase %}
```

## for
arrayに入っている全てのアイテムを表示します。
```
{% for item in array %}
  {{ item }}
{% endfor %}
```



## フィルター
フィルターを使うことで、```{{}}```内の出力結果を変更することができます。
パイプ```|```で繋げて記述することで、フィルターを呼び出すことができます。

```
{{ 'foo' | append:'bar' }}
# foobar

{{ 4.6 | ceil }} 
# 5
````

# ケース別使用例
## 販売価格をURL毎に切り替えたい
1つのテンプレートで、商品の販売価格を複数設定する場合、URL毎にルールを決めて設定します。例えば2,980円の時は、URLに「2980」、2個まとめて2,980円で販売したい時は「2980_2SET」。URLの文字列を取得し、販売価格の表示をURL毎に出し分けます。

```
{% if order.url.base_url contains '2980' %}
    この商品は、2,980円です。
{% endif order.url.base_url contains '1980' %}
    この商品は、1,980円です。
{% endif order.url.base_url contains '2980_2SET' %}
    この商品は、2個で2,980円です。
{% else %}
    この商品は、通常価格3,980円です。
{% endif %}
```
## クーポンコードを入力したユーザーに、コードに応じた割引をしたい
クーポンコードの入力アクションで真偽値を取得し、割引額の表示を出し分けます。
クーポンコード入力後の動作になるため、クーポンに関する変数は、アップセルやサンクスアップセルではないと利用できません。
```
{% assign coupon_flg = false %}
{% if order.coupon.name contains 'クーポン' %}
    {% assign coupon_flg = true %}
{% endif %}
{% if order.coupon.code contains '500' %}
    {% assign discount = '500' %}
{% elsif order.coupon.code contains '300' %}
    {% assign discount = '300' %}
{% elsif order.coupon.code contains '1000' %}
    {% assign discount = '1000' %}
{% endif %}

<p>この商品は、2,980円{% if coupon_flg %}の{{ discount }}円引き{% endif %}です。</p>
```
## 通常LPで購入した商品によって、表示を切り替えたい
通常LPで購入した商品によって、アップセル商品を切り替えたい場合に使用します。
仕様上、完全一致での条件分岐はできないため、演算子は```contain```を使用します。

```
{% assign order_item_name = order.order_items | map: 'variant' | map: 'name' | join: ', ' %}
{% if order_item_name contains '単品' %}
    2個おまとめ買いで、1,000円OFF！2,980円！
{% endif %}
{% if order_item_name contains '2個' %}
    3個おまとめ買いで、1,500円OFF！3,500円！
{% endif %}
{% if order_item_name contains '3個' %}
    4個おまとめ買いで、2,000円OFF！3,980円！
{% endif %}
```

# さいごに
基本の構文の使い方と、どの変数に何のデータが入っているかを理解していれば、いろいろ加工できそうです。

ドキュメント
https://shopify.github.io/liquid/
Pythonでベン図（matplotlib_venn）に画像を載せる

# 目的
- Pythonでカオスマップを作れないかと思い、ベン図に画像を載せる方法を調査・実験してみた

# 結果
- matplotlib_vennを使って下記のような図を作成できた
（元ネタは[こちら](https://eumag.jp/issues/c0916/)）
![output.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109639/49da7b6c-b80b-a779-ed37-914073bd1034.png)

## 大まかな流れ
- [matplotlib_venn](https://github.com/konstantint/matplotlib-venn)を使ってベン図を描画
- 画像を各領域に配置する

コード整理中につき、現状のコード全文へのリンク・より詳細にご興味がある場合は[**こちらからどうぞ**](https://lethediana.sakura.ne.jp/tech/archives/steps-ja/1430/)

## ポイント：matplotlibでの画像の扱い方
- matplotlibのOffsetImage、AnnotationBboxを作成し、AxesにArtistとして追加することで作図した
    - AnnotationBboxは、特定の位置 xy を参照する OffsetBox のコンテナであるため、OffsetImageを設定することで、グラフの設定した位置に画像を描画するArtistとすることができる
    - OffsetImageはImageを読み込めるOffsetBox（コンテナとなるArtist要素）
- OffsetImage、AnnotationBboxのクラス継承関係は下記の通り（[matplotlibのドキュメント](https://matplotlib.org/stable/api/offsetbox_api.html)の図に追記）
![image-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109639/0896c8fc-4584-5b9f-d507-640dd15205dc.png)

- 該当部分のコードは下記
```python
def im_rend(list_data, ax=None): 
    if ax is None: 
        ax = plt.gca() 
    artists = [] 
    for data in list_data:
        try: 
            data["image"] = plt.imread(data["image"]) 
        except:
            pass 
        im = OffsetImage(data["image"], zoom=data["zoom"])
        ab = AnnotationBbox(im, (data["x"], data["y"]), xycoords='data', frameon=False)
        artists.append(ax.add_artist(ab)) 
    return artists 
```
- list_dataは下記のようなデータ構造のdictionaryのリスト
```
{
    'x': (画像を表示するx座標),
    'y': (画像を表示するy座標),
    'image': (画像ファイルのパス),
    'zoom': (画像の拡大率)
}
```

下記の記事を参考にさせていただきました

https://qiita.com/sabopy/items/b4ed95f713e6d98ab52c
[Tips]GitHub Actionsのactionのバージョンもdependabotは監視してくれる

GitHubで、npmやgemなどのバージョンを最新に保つことなどを目的に、dependabotをリポジトリで管理している人や組織は多いと思いますが、GitHub ActionsのactionもアップデートするためのPRを作ってくれます。
`.github/dependabot`に下記のような記述をします。

```yaml:.github/dependabot.yml
version: 2
updates:
  - package-ecosystem: "github-actions"
    directory: "/"
    open-pull-requests-limit: 5
    schedule:
      interval: "weekly"
      day: "thursday"
      time: "19:35"
      timezone: "Asia/Tokyo"
    reviewers:
      - "Umekawa" # ここは自分のIDとか組織ならグループとか
```

これで、毎週日本時間木曜19時35分に５コマで、レビュワーがUmekawa(私のGitHubのIDです)のGitHub Actions関連のPRを作ってくれるようになります。

例として、下記のようなスクリプトを書いてみましょう。

```yml:.github/workflows/build_image.yml (必要な部分のみ抜粋)
name: Build image

on:
  push:
    branches:
      - main
  workflow_dispatch:

permissions:
  contents: read
  packages: write

jobs:
  build_image:
    runs-on: ubuntu-latest
    timeout-minutes: 30
    steps:
      - uses: actions/checkout@v1
```

[actions/checkout](https://github.com/actions/checkout)の最新バージョンはv3.1.0(v3)ですが、ここではv1になってしまっています。
しかし、設定を書いたことでdependabotがしっかり監視してくれているのでアップデートするPRを作ってくれます。

![スクリーンショット 2022-11-17 20.31.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359721/1f62f83a-243f-5e6d-1bbd-d98410a75f5f.png)

![スクリーンショット 2022-11-17 20.36.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359721/1a0abf32-01e0-f0dd-f74b-2562e29fdaf2.png)


ライブラリ関連は知らない間に老朽化していくので、ツールの力も使って楽に最新に保ちましょう。

今回のコードはここで実際に動かして検証しています。興味がある人は覗いてみてください。
https://github.com/Umekawa/github-actions-sample
rosbagの基本的な使い方まとめ

# 保存
基本的な使い方、トピック名を連続で指定して好きなトピックを保存できる。以下のコマンドの場合は/Odomトピックと/image_rawトピックと/imuトピックが保存される。

コマンドを打ったときのcurrent directoryに保存され、記録したときの時刻.bagが名前になる。
```
rosbag record /Odom /image_raw /imu
```

-aオプションですべてのトピックを保存できる。
```
rosbag record -a
```


-Oオプションでbagファイルの名前を指定できる。
```
rosbag record -O file.bag /Odom
```

-dオプションで指定秒間保存できる。
```
rosbag record -d=20 /Odom
```

-xオプションで指定のトピックを保存しない。
この場合だと/tfを除いたすべてのトピックを保存する。
```
rosbag record -a -x /tf
```



# 再生

基本的な使い方、rosbagを再生するには以下。
"rosbag.bag"は再生したいbagファイルの名前にしてください。
```
rosbag play robot_bag.bag
```

-lオプションでリピート再生できる。
```
rosbag play -l robot_bag.bag
```

-uオプションで最初から指定秒間再生する。
この場合は0~40秒までを再生する。
```
rosbag play -u 40 robot_bag.bag
```

-sオプションで指定秒後から再生する。
この場合は40秒~最後までを再生する。
```
rosbag play -s 40 robot_bag.bag
```

-rオプションで倍速再生できる。
この場合は2倍再生。
```
rosbag play -r 2.0
```

--clockオプションでROS時間を通知する/clockトピックを送信する。
```
rosbag play robot_bag.bag --clock
```


連続して書けばオプションを複数付けれる。
この場合は2倍速で、40秒〜再生して、clockトピックも送信する。
```
rosbag play -r 2.0 -u 40 --clock robot_bag.bag
```

なお、オプションは以下のように後ろにも付けることができる。
```
rosbag play robot_bag.bag -r 2.0 -u 40 --clock
```





# その他


rqt_bagコマンドでどのようにトピックが記録されたかが見れる。
rosbag recordした後に目的のトピックがきちんと保存できているかの確認でもよく使われる。

出てきたウィンドウの左側にあるトピック名を右クリック→View→Plotで値がグラフ表示できる。
```
rqt_bag robot_bag.bag
```



infoでrosbagの情報が見れる。
```
rosbag info robot_bag.bag
```

# 参考

rosbagコマンドのオプションが記載されてるwikiはここ。
http://wiki.ros.org/rosbag/Commandline
Emergency-braking systems ボッシュ自動車handbook 11版(154) p.1916

Drive assistance and sensors, Emergency-braking systems ,  ボッシュ自動車handbook 11版(154)

人生で影響を受けた本100冊。

https://qiita.com/kaizen_nagoya/items/16af53acbb147a94172e

に掲載した本のうち、「新人プログラマ応援」企画で「私の推薦書３３冊」として３３冊紹介した。

新人プログラマ応援　私の推薦書３３冊

http://qiita.com/kaizen_nagoya/items/98c62f051dbdb4f8aca2
残りの６７冊から、順に過去の読書感想を引用し、新たな読書感想文を追記する。

 <この項は書きかけです。順次追記します。>


# ボッシュ自動車ハンドブック version 11, 2022

Automotive Handbook  May 2, 2022

https://www.amazon.co.jp/dp/1119911907/

ボッシュ自動車handbook(英語)11版(0-1) 課題と記事一覧new

https://qiita.com/kaizen_nagoya/items/a9d2887bf2a7598dc8e5

# Contents
Motor vehicle, 28
Basic principles, 32
Mathematics and methods, 204
Materials, 258
Machine parts, 354
Joining and bonding techniques, 426
Vehicle physics, 462
Operating fluids, 538
Refrigerants for air-conditioning systems, 591
Drivetrain(駆動系), 594
Internal-combustion engines(内燃機関),642
Management for spark-ignition engines,800
Gasoline-engine operation with alternative fuels, 886
Management for diesel engines, 906
Electrification of the drive, 970
Emission-control and diagnosis legislation, 1042
Chassis systems, 1108
Vehicle bodies,  1310
Comfort and convenience, 1392
Safety systems in the motor vehicle, 1410
Vehicle security systems, 1430
Automotive electrics, 1450
Vehicle electrical systems for hybrid and electric vehicles, 1560
Automotive electronics, 1620
Infotainment 1780
Drive assistance and sensors, 1804
Drive assistance systems 1872
Future of automated driving 1934
Appendics, 1940

# Emergency-braking systems , p.1916

## Emergency-braking systems in longitudinal traffic
## Maneuver emergency braking
## Automatic emergency braking ofr unprotected road users

# Reference
[3] UN ECE R131 
Regulation No 131 of the Economic Commission for Europe of the United Nations (UN/ECE) — Uniform provisions concerning the approval of motor vehicles with regard to the Advanced Emergency Braking Systems (AEBS)

https://op.europa.eu/en/publication-detail/-/publication/302d6594-0f02-11e4-a7d0-01aa75ed71a1


# 自己参考資料(self reference)

ボッシュ自動車ハンドブック 

https://qiita.com/kaizen_nagoya/items/8e330ce57880f04d71d9
ボッシュ自動車handbook(英語)10版　目次

https://qiita.com/kaizen_nagoya/items/57c799ff544c96efdea9

自動車工学とBosch Vehicle Handbook

https://qiita.com/kaizen_nagoya/items/d13ff6b0e4d7c8907c0d

 ＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞

# 文書履歴(document history)
ver. 0.01 初稿 20221117
react testing libraryとjestでReact UTの準備のためのtool比較

最近になってTDD(test-driven development、テスト主導開発)という言葉がもっとよく聞こえるようです。

失敗するテストコードを作っておいて、

そのテストを通過する本物のコードを作成し、

修正することがあればリファクタリングする方式ですが。

そうすれば、小さな機能単位で開発することになるので、すっきりとした良いコードを維持できるようになります。


## 1.テストの種類:ユニットテストとは？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2662677/64cd9e97-f93d-6a36-39ff-203a3d50e239.png)
フロントエンドテストは大きく3種類あります。

- E2E(End to End)テストは、プロジェクトがブラウザ上で正常に動作するかどうかをユーザーの観点からテストする方法です。 通常、SeleniumやPuppeteerなどを使用します。

- 統合(Integration)テストは機能単位でまとめてテストする方法で、通常ユニットテストが終わったモジュールをまとめて確認します。 複数のコンポーネントがうまく相互作用し、レンダーになるか、DOMイベントが発生したときに必要なUIの変化が起こるかなどをチェックします。

- UT(ユニットテスト)は、最小単位で機能がうまく機能するかどうかを確認する方法です。 コンポーネントがよくレンダーになっているか、特定の関数がうまく機能しているかなどを見ることです。

 そして今度はユニットテストについて見ていきたいと思います。


## 2. react testing tools
通常、javascriptをテストするには、次のツールを使用できます。

- Karma
- Jasmine
- Jest
- Chai
- Mocha

私はJestをよく使いますが、Jestはインストールと起動が簡単です。 そしてMetaで制作したフレームワークなので、Reactとよく合うと思います。 

そしてDOMをテストするためのツールとしては、Airbnbで2015年から開発したEnzymeと2018年から開発されたreact-testing-libraryが最も有名です。 

Enzyme と react-testing-library は両方ともコンポーネントテストを行いますが、それぞれ異なる哲学を持っています。 Enzyme を使用するときは、コンポーネントの内部のProps、Stateを確認するなど、コンポーネントの内部機能に頻繁にアクセスします。
 一方、react-testing-libraryは、rendering結果により集中します。 コンポーネント内部の動作よりは、実際の画面にどのようなものが表示されるのか、DOMについて気を使うのです。

私はReact公式文書で推薦していて、内部動作よりは簡単にrenderingされた結果だけをテストしたくてreact-testing-libraryを選択しました。


※ CRA(create-react-app)で始めると、jestは自動的にインストールされています。
※ react-testing-libraryはjestフレームワークでよく使用されますが、必ずしもjestのように書く必要はありません。

※ 複数箇所でリファレンスを参考にした個人の投稿です
再帰関数を使って階乗を求めるメソッドを作成する(Ruby)

# 初めに

アルゴリズムを利用した方法で再帰関数がよく使われるので
階乗を求める再帰関数を作成して理解を深めます。

# そもそも再帰関数とは？

アルゴリズムなどを記述するときに、
自分自身を引用する形で定義することを**再帰的定義**といい
自分自身を呼び出す関数のことを**再帰関数**といいます。

# 再帰関数で注意すること

:::note info
1：自分自身の関数を用いて、問題を少し簡単にするための計算式をたてます
:::
:::note warn
2：無限ループにならないように**ベースケース**を作成します。
:::
階乗を求める関数factorialを作成してみましょう。
# 階乗(factorial)を求めるメソッド
```ruby:ruby
def factorial(n) 
  if n <= 0  
  # 0! = 1 なので1を返します。(※ここがベースケース)
     return 1
  else
   #※1：動作確認用
   p n
   #※2:ここでfactorial自身を呼び出します
   return n * factorial( n - 1 ) 
  end
end
# 計算結果を出力(120が出力される)
p factorial(5) 
```
5! = 120なので問題ないですね。
# ※1の動作確認用の`p n`の部分で動きを確認すると・・・
```ruby
5
4
3
2
1
```
↑のようにnの値が変化していることを確認できます。

# ※2の部分を `p n * factorial( n - 1 )` に変更して動きを確認すると・・・
```ruby
1
2
6
24
120
```
↑のように出力されることが確認できます。
これは再帰関数を使わない、each,times,whileなどのようなループとは挙動が違い、初めて使う場合はなぜこのようになるのか混乱してしまいます。

そこでpコマンドなどで処理の流れを見ることでどうなっているのか確認します。

# ※2の部分を `p "#{n} * #{factorial( n - 1 )}"` に変更して処理を確認してみると・・・
```ruby:
"1 * 1"
"2 * 1 * 1"
"3 * 2 * 1 * 1"
"4 * 3 * 2 * 1 * 1"
"5 * 4 * 3 * 2 * 1 * 1"
"5 * 4 * 3 * 2 * 1 * 1"
```
↑のように計算していることがわかりますね。
以下のように動いているようです。
# 再帰関数の処理の流れ

:::note info
1：factorial(5)はfactorial(4) × 5 を返すことになっているので、関数factorial(4)を呼び出します。
2：factorial(4)はfactorial(3) × 4 を返すことになっているので、関数factorial(3)を呼び出します。
3：factorial(3)はfactorial(2) × 3 を返すことになっているので、関数factorial(2)を呼び出します。
4：factorial(2)はfactorial(1) × 2 を返すことになっているので、関数factorial(1)を呼び出します。
5：factorial(1)はfactorial(0) × 1 を返すことになっているので、関数factorial(0)を呼び出します。
:::
:::note warn
6：factorial(0)はN<=0の条件をみたすので1を返します。
:::
:::note info
7：factorial(1)はfactorial(0)の呼び出しが終わったので**1 × 1 = 1**を返します。
8：factorial(2)はfactorial(1)の呼び出しが終わったので**2 × 1 × 1 = 2**を返します。
9：factorial(3)はfactorial(1)の呼び出しが終わったので**3 × 2 × 1 × 1= 6**を返します。
10：factorial(4)はfactorial(1)の呼び出しが終わったので**4 × 3 × 2 × 1 × 1 = 24**を返します。
11：factorial(5)はfactorial(1)の呼び出しが終わったので**5 × 4 × 3 × 2 × 1 × 1 = 120**を返します。
:::

# 終わりに
**再帰関数**の処理の流れを見ることでどのように動いているか理解を深めることができました。
Lane-change assistant, ボッシュ自動車handbook 11版(153) p.1912

Drive assistance and sensors, Lane-change assistant ,  ボッシュ自動車handbook 11版(152)

人生で影響を受けた本100冊。

https://qiita.com/kaizen_nagoya/items/16af53acbb147a94172e

に掲載した本のうち、「新人プログラマ応援」企画で「私の推薦書３３冊」として３３冊紹介した。

新人プログラマ応援　私の推薦書３３冊

http://qiita.com/kaizen_nagoya/items/98c62f051dbdb4f8aca2
残りの６７冊から、順に過去の読書感想を引用し、新たな読書感想文を追記する。

 <この項は書きかけです。順次追記します。>


# ボッシュ自動車ハンドブック version 11, 2022

Automotive Handbook  May 2, 2022

https://www.amazon.co.jp/dp/1119911907/

ボッシュ自動車handbook(英語)11版(0-1) 課題と記事一覧new

https://qiita.com/kaizen_nagoya/items/a9d2887bf2a7598dc8e5

# Contents
Motor vehicle, 28
Basic principles, 32
Mathematics and methods, 204
Materials, 258
Machine parts, 354
Joining and bonding techniques, 426
Vehicle physics, 462
Operating fluids, 538
Refrigerants for air-conditioning systems, 591
Drivetrain(駆動系), 594
Internal-combustion engines(内燃機関),642
Management for spark-ignition engines,800
Gasoline-engine operation with alternative fuels, 886
Management for diesel engines, 906
Electrification of the drive, 970
Emission-control and diagnosis legislation, 1042
Chassis systems, 1108
Vehicle bodies,  1310
Comfort and convenience, 1392
Safety systems in the motor vehicle, 1410
Vehicle security systems, 1430
Automotive electrics, 1450
Vehicle electrical systems for hybrid and electric vehicles, 1560
Automotive electronics, 1620
Infotainment 1780
Drive assistance and sensors, 1804
Drive assistance systems 1872
Future of automated driving 1934
Appendics, 1940

# Lane-change assistant , p.1912
## Blind-spot assistant 
## Lane-change assistant
## Evasive steering support 
## Further developments 

# Reference
[1] Commission Regulation (EU) No. 351/201 of 23  implementing Regulation (EC) No 661/2009 of the GIDAS(German in Depth Accident Study) 2014, http://www.gidas.org
# 自己参考資料(self reference)

ボッシュ自動車ハンドブック 

https://qiita.com/kaizen_nagoya/items/8e330ce57880f04d71d9
ボッシュ自動車handbook(英語)10版　目次

https://qiita.com/kaizen_nagoya/items/57c799ff544c96efdea9

自動車工学とBosch Vehicle Handbook

https://qiita.com/kaizen_nagoya/items/d13ff6b0e4d7c8907c0d

 ＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞

# 文書履歴(document history)
ver. 0.01 初稿 20221117
【SwiftUI】RenameButtonってものが追加されてるけどこれ意味なくね？？

# はじめに
SwiftUIに[RenameButton](https://developer.apple.com/documentation/swiftui/renamebutton)というUIコンポーネントが追加されていました。
iOS16から使用できます

# デザイン
![スクリーンショット 2022-11-17 20.01.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/9eb152c0-6940-7a52-9b1f-1e280cbcb298.png)
ボタンスタイルが使用できます。
しかし、アイコンやテキストは変更できないっぽいです。

# 使い方
```swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        RenameButton()
            .renameAction {
                // ここにアクション
            }
    }
}
```
ん？これ`Button`で良くね？

# おわり
使い方が間違ってる？？
何をするボタンかは一瞬でわかるのでいいかも？？
Basic認証


# ユーザー認証を導入


## 開発環境で環境変数を設定
※macOSがCatalina以降の場合

たとえば

<b>「xxxx」</b>というユーザー名と
<b>「0000」</b>というパスワードにて、設定をする場合。

##### ①ターミナルで以下を実行する
```Terminal:ターミナル
vim ~/.zshrc
```
すると、「~」が縦に大量に表示される。

##### ②「i」を押下し「インサートモード」にする
「-- INSERT --」と最下部に表示される。

##### ③zshの内部に、以下の記述を追加
```Terminal:ターミナル
export BASIC_AUTH_USER='xxxx'
export BASIC_AUTH_PASSWORD='0000'
~
~
~
~
-- INSERT --
```

##### ④インサートモードを終了
「escキー」→ 「:wq」→「Enterキー」を押して終了。

##### ⑤sourceコマンドを実行
```Terminal:ターミナル
source ~/.bash_profile
```

##### ⑥環境変数をRailsアプリケーション側で読み込む

「app/controllers/application_controller.rb」を以下のように記述。
```Ruby:app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  before_action :basic_auth


  private

  def basic_auth
    authenticate_or_request_with_http_basic do |username, password|
      username == ENV["BASIC_AUTH_USER"] && password == ENV["BASIC_AUTH_PASSWORD"]
    end
  end
end
```

## 本番環境で環境変数を設定

①ダッシュボードを開き該当するアプリ名をクリック
②「Environment」をクリックし以下のように環境変数を設定
|Key|	Value|
|-|-|
|BASIC_AUTH_PASSWORD|0000|
|BASIC_AUTH_USER|xxxx|

#techcamp136期
MANA入手までの道のり（暗号資産について）

![スクリーンショット 2022-11-13 18.48.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524398/19e84bd0-9389-5544-2827-bf40503ca010.png)

「仮想通貨ってなんか怖い、、」
予てからメタバース事業にて創造的なお話をしてきた我々ですが、ついに恐れていた（知見の無い）仮想通貨に関わらなければいけない事態となった。
これが想像以上に大変だったので、その苦労の内容と検討結果をまとめてみたので、同じ様な境遇の人は参考にしてほしい。

## 仮想通貨検討までの経緯
弊社では今「Decentraland」の利用を検討している。
同プラットフォームは基本的に無料で楽しむ事が出来るメタバース空間だが、服や土地などを購入する時にはお金が必要となる。そこで利用する”お金”が「__MANA__」という訳だ。
そんな仮想通貨のMANAだが皆んな正直「買うだけでは?」と思うだろう。
ただ初心者が、MANAを、法人として入手するにはそれなりの苦労があるようだ。これらの課題をクリアしながら検討を重ね、後に具体的な手順を記述したので順番に見て欲しい。

## マネーリテラシーの学習
![KABU.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524398/58042c35-ea2a-a354-9deb-0d60bd08af69.png)
そもそも金融商品を扱う上で気になるのはまず税金だ。利益が出れば当然課税される訳だが、これだけ激しく価値が変動する暗号資産で利益/損出を最小限にするのは至難の業だ。挙句の果てには商品を購入した時にも課税されるそうなので、これも考慮が必要だ。
暗号資産を手に入れる方法も「日本円で購入すればいい」という単純なものだけではない。またそこにかかる手数料も場合によっては「スプレット」「送金手数料」「入出金手数料」などと、あの手この手で引かれていくため、実際に始める際はその時に詳細を調べてほしい。
> 参考：
[「Money Method」暗号資産(仮想通貨)にかかる税金の種類とは？課税方法や　ペナルティを紹介](https://www.kobe-np.co.jp/media-money/contents/cryptocurrency/cryptocurrency-tax)

## MANA入手までの手順
「MANA」という仮想通貨を入手するまでには少し手間がかかる。
BitcoinやETHみたいなメジャー仮想通貨は日本円から直接購入する事も可能だ。
しかし、メジャーでない仮想通貨はそうはいかない。日本円から一旦ETHなどのメジャーな仮想通貨を手に入れ、それをMANAに両替していく必要がある。（両替以外にも交換や購入をする方法もある）それに加えそもそも扱っている業者も限られてくるため条件に合う業者の選定も一苦労だが、その件に関しては以下に続く。

## 法人として活動する
![bitFlyer Lightning.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524398/e5c319ed-d4a2-5e05-e7a5-59f12007fa31.png)
法人として活動する以上、上記の観点に加え日本の許可（金融庁の登録）を得ている業者を選定したい。これは意外だったのだが、あの有名なBINANCEでさえ2022年11月現在、日本の許可が下りていないため、日本の法人として取引するのは憚れる。
更にその中から”法人として口座開設が出来る業者”を選ばなければいけない。（個人口座でも問題無いかもしれないが慎重を期して、、）
、、もはや聞いた方が早いということになりbitflyerに問い合わせた結果「bitflyer lightning」を使用してほしいとのことで、その後申請し無事、法人口座を開設することが出来た。
> 参考：
[「MINKABU」仮想通貨のホワイトリストとは？登録通貨一覧と安全性や登録の条件を徹底解説](https://minkabu.co.jp/choice/cc-crypt-whitelist/)

## Decentralandでモノを買うまでの手順
という訳で以上の事情に鑑み、最終的に我々は以下の方法で入手することにした。

__1. bitFlyer Lightningにて日本円からETHの購入__
　➡︎bitFlyer Lightningにて法人口座を開設し日本円を送金。その日本円でETHを購入

__2. ETHをbitFlyer LightningからMetaMask（ウォレット）に送金__
　➡︎送金時、アドレスのと方法の妥当性検証のため、事前に少額取引を行う。

__3. ETHをMANAにスワップ（両替的な）__
　➡︎METAMASK上でETHからMANAにスワップを行う。

__4. Decentralndにてアセットを購入__
　➡︎METAMASKとDecentralndは事前に紐づけているので、MARKETPLACEにてアセット（土地など）を購入

## まとめ
ざっくりまとめると、「税金」「取引方法と付随する手数料」「法人として何の活動をするか」は事前にハッキリさせるべきだ。今回はあくまで考慮すべき観点とさわりの部分の話をしたが、手順が一つ変わると全体のフローもガラッと変わる可能性もあり、上記手順に時間を要してしまうと暗号資産の価格も変動し意図しない利益/損失も出てしまうため、手順書を作成して検証をすることをお勧めする。

![スクリーンショット 2022-11-13 21.32.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524398/6f1ac4cf-7ce0-f8b3-4e89-2e289d530e35.png)
テキストの写真を読み込んで音声ファイルにする簡単なアプリケーションの作成

Pythonの学習の整理として、簡単なアプリケーションを作成してみることにした。

受験の時欲しかった、過去問などの写真を撮ると、音声ファイルに変えてくれるアプリを作成して、デプロイしてみることにした。

全体の方針として、
・画像からテキストへはGCPのGoogleCloudVisionを使用。
・テキストから音声ファイルへの変換はGCPのTexttoSpeechを使用。
・インターフェイスはpythonのStreamlitを使用する。

という感じだ。

作成したアプリのコードは以下のようになる。

https://github.com/Sanban-curry/photho_to_speech


また、Herokuにてデプロイしたアプリはこちらになる。

https://phototospeech.herokuapp.com/

簡単に流れを言うと、GCPのAPIをそれぞれ有効化したあと、GCPのGoogleCloudVisionとText-to-Speechのクイックスタートをコピペして使う部分だけ残し、それぞれを書き加える。その後、きちんと動作するかを確かめたら、streamlitを用いて簡単なフロントエンドを作成していく。そして、動作確認後、デプロイして動作確認。修正をする。

プログラミング初心者でも調べながら2日弱で作成することが出来た。良い経験になった。

参考にしたサイトは下に貼る。

https://qiita.com/myonoym/items/c9a90bc9a610c5217ac3

https://tekuzo.org/visionapi-ocr2txt/

公式のドキュメント

https://cloud.google.com/text-to-speech/docs/libraries?hl=ja





そして、発生したトラブルの対処は下のページにある。


https://www.notion.so/GoogleCloudVision-2022-11-16-38d49f0c84d345e9a34fc6bd78c188ef

https://www.notion.so/heroku-2022-11-17-7f5ed524ac754822914e66d28a25bcd4

https://www.notion.so/img-path-2022-11-17-1b45811a4b4340c7b9e2d6a09c3d5721
【AWS】AMI作成後、502 Bad Gatewayエラーが発生する場合の対処方法

# 概要
ALBの振り分け先WEBサーバを複数用意するため、
- 既存のEC2インスタンスのAMIを作成
- 新規インスタンス起動時に上記で作成したAMIを利用
- ALBのターゲットグループに新しく作成したインスタンスを追加

した上でアクセスすると、
> 502 Bad Gateway

のエラーが発生し、アクセスできない状態となった。

# 環境
- アプリ
  - ruby 3.0.2
  - rails 6.1.4
  - mysql 8.0.31

- EC2AMI
    - Amazon Linux2 AMI 
    - app server : Unicorn
    - web server : Nginx

# 原因
- AMI作成時、作成元のEC2インスタンスは再起動される
- サーバの再起動により、Nginxが停止したことで、そもそもアプリが起動しておらず、接続できなくなっていた


> 参考

https://docs.aws.amazon.com/ja_jp/toolkit-for-visual-studio/latest/user-guide/tkv-create-ami-from-instance.html

https://tracl.cloud/archives/engineerblog/what-is-ami

# 対策
サーバ起動時にNginxも起動するようにしておく
> 参考

https://qiita.com/kouki_o9/items/fcf8dfd1ed999f284a56

ALB関連の設定が悪さをしていると思い込んでいましたが、初歩的なミスでした、、、。
ちなみに、502 Bad Gatewayの状態だと、
- セキュリティグループ的に問題なくてもcurlでConnection refusedされる

```terminal
❯❯❯ curl -v XX.XX.XX.XX(接続先パブリックIPアドレス)
*   Trying XX.XX.XX.XX...
* TCP_NODELAY set
* Connection failed
* connect to XX.XX.XX.XX port 80 failed: Connection refused
* Failed to connect to XX.XX.XX.XX port 80: Connection refused
* Closing connection 0
curl: (7) Failed to connect to XX.XX.XX.XX port 80: Connection refused
```
- EC2上の/var/www/my-app/current/log以下のproduction.logやunicorn.stderr.logには何も書き込まれない
状態になります。当然か。
Bitnami が提供する WordPress 用のイメージは PHP を更新することはできません


## はじめに

Amazon Lightsail for Bitnami WordPress を利用し作成されたサーバーの OS やミドルウェアの更新を検討していたが思わぬ所に躓いたので記事にしました

## 結論

タイトルの通り、 Bitnami が提供する WordPress 用のイメージを用いてサーバーを構築している場合
旧サーバー内のデータやコンテンツをエクスポートし、新サーバーにインポートする必要があります

## どうすると良いか

- [Bitnami Documentation] に記載されているエクスポート方法として、 [All-in-One WP Migration] を利用する方法が記載されていました

https://docs.bitnami.com/aws/how-to/migrate-wordpress/

https://wordpress.org/plugins/all-in-one-wp-migration/

手順はとても簡単で

1. 旧サーバーで
   1. WordPress Plugin [All-in-One WP Migration] をインストールし有効化する
   1. WordPress のコンテンツ/データをエクスポートする
1. 新サーバーで
   1. 旧サーバーからエクスポートしたデータをインポートする

新しい WordPress サーバーの構築は [Bitnami Documentation] のドキュメントを参考にしてください

https://docs.bitnami.com/aws/how-to/get-started-wordpress-aws-marketplace-beginner/

[Bitnami Documentation]: https://docs.bitnami.com/
[All-in-One WP Migration]: https://wordpress.org/plugins/all-in-one-wp-migration/

## References

https://docs.bitnami.com/aws/how-to/migrate-wordpress/

https://github.com/bitnami/vms/issues/207#issuecomment-1205022832

https://stackoverflow.com/questions/73947826/how-can-i-upgrade-php-in-bitnami-wordpress-stack

https://blog.duaneleem.com/upgrade-aws-lightsail-bitnami-wordpress-using-all-in-one-wp-migration-plugin/
git submoduleとは

gitのsubmoduleについて初めて触ったので備忘録としてメモ

## git submoduleとは
git submoduleとは、外部のgitリポジトリを、自身のgitリポジトリのサブディレクトリとして登録し、特定のcommitを参照する仕組み。

## git submodule add
```bash
$ git submodule add [サブプロジェクトのリポジトリURL]
```
と行うことで、作業中のリポジトリに、サブモジュールとして既存のリポジトリを追加することができる。

これを行うことで、.gitmodulesファイルがルートディレクトリに追加される。
```.gitmodules
[submodule "submoduleの名前"]
    path = submoduleの名前
    url = submoduleのURL
```

複数のサブモジュールを追加した場合は、このファイルに複数のエントリが追加される

## 参照
https://qiita.com/sotarok/items/0d525e568a6088f6f6bb
https://git-scm.com/book/ja/v2/Git-%E3%81%AE%E3%81%95%E3%81%BE%E3%81%96%E3%81%BE%E3%81%AA%E3%83%84%E3%83%BC%E3%83%AB-%E3%82%B5%E3%83%96%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB
プロフェッショナルの仕事

![スクリーンショット 2022-11-17 18.01.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/b210ce53-3cf2-08e8-9901-67a504173026.png)

会社に属した従業員の立場や会社を創業して取締役としてやっている立場やフリーで契約して働く立場等色んな立場はあるが、お金を貰って働いている以上、皆、プロフェッショナルである。

本当の意味で自分をプロフェッショナルであると意識して働いている人はどの位いるのだろうか。

これは、どの様な職種であっても共通する事だと思う。

自分はエンジニアであるので、エンジニアという職種において、何をもってプロフェッショナルなのかを理解する必要がある。

単純にプログラミングができるだけでは、本当の意味でのプロフェッショナルには、程遠い。
システム設計ができても、プロフェッショナルとしては不十分である。

いわゆる世の中でいう、システムエンジニア（SE)、プログラマーでは、プロフェッショナルとして不十分だという事である。

エンジニアは、ある事業に対してシステムアプローチで事業を牽引する役割を持った人。
＊ここではITエンジニアとしての定義が違いと思う。

つまり、自分が属している会社のビジネスを理解し、その会社の売上げ対象となる利害関係者の立場を理解し、システム担当として最適なソリューションを判断し、構築できてこそ、プロフェッショナルである。

そのためには、
・常に情報収集を行い、外部環境の動きを把握する
・常に創造性を働かして、ソリューションを考える
・常にある側面だけでは無く、全体最適化を意識する

常にプロフェッショナルとしてのマインドを意識して行きたいと行動していきたいと思う。
DBの正規化とは

# 目次
- DBの正規化とは
  - [第一正規化](#第一正規化)
  - [第二正規化](#第二正規化)
  - [第三正規化](#第三正規化)
- [まとめ](#まとめ)

データの不整合が起きるこの腐った世の中に終止符を打とうとこの記事を投稿します。

大昔に作られたサイトは同様に大昔に作られたガイドラインの上に成り立っているのですごくイけてないコードを見て改修案を出すのですが、
マニュアルなのか呪縛なのか、一向にコードのリプレースを検討してくれない。システムがそれだったらデータベースももちろん。。
なんて毎日データベースの補正案件を頼まれることを杞憂しているタコパーティです。

# DBの正規化とは
データベース上で扱うデータの重複の削除など、最終的に効率的なDB操作ができてスマートな形にすることだと思います。

**質の低いデータベース**

**注文を受けたらその内容をどんどん追加していくテーブル**
**注文を整理したテーブル**
があるとしよう。そのテーブルにもし注文のキャンセルが起きた場合、キャンセルされた内容は**注文を受けたらその内容をどんどん追加していくテーブル**と**注文を整理したテーブル**同時にカラムを削除しなければいけない。ではないと矛盾が生じてしまうからである。
解決方法としては、あらかじめデータベースを正規化しておく必要がある。

# 第一正規化

| 注文先 | 住所 | 社長 | 電話番号 | 単価 | 入荷日 | 入荷数 | 商品名 | 備考 |
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
| たこぱ果樹園  |  栃木 |  たこぱ | 080-1111  | 100  |  11/10 |  10 |  いちご |  とちおとめ |
|   |   |   |   | 200  | 11/10 |  10 |  ばなな |   |
|   |   |   |   | 100  | 11/11  |  20 |  いちご | とちおとめ  |
| Fujitora農場  |  東京 |  Fujitora | 070-1111  |  150 | 11/12  | 30  | きのこ  |   |

このようなテーブルがあったとしましょう。第一正規化のポイントは**冗長性の削除と繰り返しすレコードの整理です**

| 注文先 | 住所 | 社長 | 電話番号 | 単価 | 入荷日 | 入荷数 | 商品名 | 備考 |
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
| たこぱ果樹園  | 栃木  | たこぱ  | 080-1111  |100 | 11/10  | 10  | いちご  | とちおとめ |
| たこぱ果樹園  | 栃木  | たこぱ  | 080-1111  |200 | 11/10  | 10  | ばなな  |   |
| たこぱ果樹園  | 栃木  | たこぱ  | 080-1111  |100 | 11/11  | 20  | いちご  | とちおとめ  |
| Fujitora農場| 東京  | Fujitora| 070-1111  |150 | 11/12　| 30  | きのこ  |   |

先ほどよりもデータベースがはっきりと分かるようになってきたのではないでしょうか？

# 第二正規化

関数従属性を考慮したテーブルの作成。
つまり、第二正規化とは、「このテーブルにたった1つしかないレコーであることを証明できる状態にすること。」だと自分は思っています。
さっきのテーブルを例に第二正規化を行っていきましょう。

**商品テーブル**
| 商品名 | 単価 | 備考 |
|:-:|:-:|:-:|
| いちご  | 100  | とちおとめ  |
| ばなな  | 200  |   |
| きのこ  | 150  |   |

**注文テーブル**
| 商品名 | 注文先 | 入荷日 | 入荷数 |
|:-:|:-:|:-:|:-:|
| いちご  | たこぱ果樹園  | 11/10  | 10  |
| ばなな  | たこぱ果樹園  | 11/10  | 10  |
| いちご  | たこぱ果樹園  | 11/11  | 20  |
| きのこ  | Fujitora農場  | 11/12  | 30  |

商品名を主キーにすれば、商品名から注文先情報も、逆に注文テーブルも商品名さえあれば、商品テーブルがわかるようになる。

# 第三正規化

第二正規化で二つに分けたテーブルの中で見当たらなかったカラムがあると思います。それが社長にかかわるカラム。
このカラムももちろんテーブル化していくのですが、社長が変わった際に、元の社長の値が入っているテーブルをそれぞれ変更するのも
とても非効率的なのでしっかりとテーブルを分けていきましょう。

**商品テーブル**
**注文テーブル**
第二正規化と同じ内容

**注文会社テーブル**

| 注文会社 | 住所 | 社長 |
|:-:|:-:|:-:|
| たこぱ果樹園  | 栃木  | たこぱ  |
| Fujitora農場  | 東京  | Fujitora  |

**個人情報テーブル**
| 名前 | 電話番号 |
|:-:|:-:|
| たこぱ  | 080-1111  |
| Fujitora  | 070-2222  |

# まとめ

正規化をする上で大切なのは、問題が起こったときに効率的に対処するためにデータを整理整頓することと、
そもそも問題が起こらないようにする。冗長している部分（いらないカラムがあるなど）は削除する。のちにデータを入れ替えない部分を考慮してテーブルを分けておく対策にすること。などやっぱり正規化って大切だなと。。つくづく思います。