OmniAICreator/Qiita-1.07M huggingface dataset:
Discord.pyのアップデート

# はじめに
つい最近Discord.pyのアップデートが来たので、「久々にBot起動してみたらイミフなエラーはいてて起動できない!!」みたいな人がいるのではないでしょうか？
そんな人のために、今回はDiscord.pyのアップデート方法を書きました。

# エラー
```python
Traceback (most recent call last):
  File "main.py", line 219, in <module>
    bot.run("")
  File "C:\Users\\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\client.py", line 640, in run
    return future.result()
  File "C:\Users\\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\client.py", line 621, in runner
    await self.start(*args, **kwargs)
  File "C:\Users\\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\client.py", line 585, in start
    await self.connect(reconnect=reconnect)
  File "C:\Users\\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\client.py", line 499, in connect
    await self._connect()
  File "C:\Users\\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\client.py", line 463, in _connect
    await self.ws.poll_event()
  File "C:\Users\\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\gateway.py", line 471, in poll_event
    await self.received_message(msg)
  File "C:\Users\\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\gateway.py", line 425, in received_message
    func(data)
  File "C:\Users\\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\state.py", line 750, in parse_guild_create
    guild = self._get_create_guild(data)
  File "C:\Users\\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\state.py", line 725, in _get_create_guild
    guild._from_data(data)
  File "C:\Users\\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\guild.py", line 297, in _from_data
    self._sync(guild)
  File "C:\Users\\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\guild.py", line 324, in _sync
    self._add_channel(TextChannel(guild=self, data=c, state=self._state))
  File "C:\Users\\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\channel.py", line 107, in __init__
    self._update(guild, data)
  File "C:\Users\\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\channel.py", line 131, in _update
    self._fill_overwrites(data)
  File "C:\Users\\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\abc.py", line 294, in _fill_overwrites
    self._overwrites.append(_Overwrites(id=overridden_id, **overridden))
TypeError: __new__() got an unexpected keyword argument 'deny_new'
```
久々にBot起動してみたらこんなエラーが出てた!!って人はDiscord.pyのアップデートをしてみてください。

# アップデート方法
```pip
pip install -U discord.py
または
pip install --upgrade discord.py
```
これでアップデート完了です！起動してみてください。

# 最後に
新しいBotを作りました！
広告を簡単に追加したり表示したりできるBotです。
ぜひ導入してみてください！

[公式サポートサーバー]
https://discord.gg/SjKNtr6

[招待URL]
https://discord.com/api/oauth2/authorize?client_id=729317389803716658&permissions=523328&scope=bot
Miroのジェスチャーの変更

## 概要

Windows版デスクトップアプリケーションのMiroを利用していたら、
操作方法が違っていてかなり頭が混乱したので、操作方法の変更方法。

## まとめ

Miroには`Navigation mode`で2パターンの操作方法が選べる模様。

- Mouse
    - ホイールで**ズーム**
    - ドラックで**移動**
- TrackPad
    - ホイールで、**縦横移動**
    - ドラックで**選択**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679477/ca83d1d2-59a7-9901-a6da-5e7ba2d88805.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679477/53e46a1b-2e20-f88a-db10-b30c78216275.png)
Pythonの組み込み関数openのモックを作って単体テストする

# 組み込み関数を使っているメソッドの単体テストを行う
実ファイルを使わずにテストしたい場合、ファイルopenメソッドのスタブ(モック)を作ってテストします。

- `unittest`モジュールを使う
- `mock_open`という便利なメソッドがある
- `open`のような`組み込み関数`のモックを作成する場合は、名前に`builtins`を使い、`builtins.open`のように書く
- `mock_open(read_data='str1¥nstr2¥n')`のように、モックのファイルから読み出すデータを指定できる

# サンプルコード

## (テストしたいファイル。ファイルの読み書きを行っている)

```python
# file_mock_sample.py

class FileMockSample:
    def my_func_1(self):
        path1 = '/tmp/not_exist_file_1.txt'
        with open(path1, mode='r') as f1:
            lines = f1.readlines()
            print(lines)    # ['line 1\n, 'line 2\n', 'line 3']
        return lines

    def my_func_2(self):
        path2 = '/tmp/not_exist_file_2.txt'
        with open(path2, mode='w') as f2:
            f2.write('line1\n')
            f2.write('line2\n')
            f2.write('line3\n')
```


## (テストコード。`mock_open`を使ってファイルのモックを作成してテストする)

```python
# test_file_mock_sample.py
from unittest.mock import patch, mock_open

from file_mock_sample import FileMockSample

class TestFileMockSample:
    def test_my_func_1(self):
        dt = 'readline1\nreadline2\nreadline3\n'
        mock_io = mock_open(read_data=dt)
        # openは組み込み関数なので、「builtins」を使う
        with patch('builtins.open', mock_io):
            fm = FileMockSample()
            result = fm.my_func_1()
            mock_io.assert_called_once_with('/tmp/not_exist_file_1.txt', mode='r')
            assert result == ['readline1\n', 'readline2\n', 'readline3\n']

    def test_my_func_2(self):
        mock_io = mock_open()
        # openは組み込み関数なので、「builtins」を使う
        with patch('builtins.open', mock_io):
            fm = FileMockSample()
            fm.my_func_2()
            mock_io.assert_called_once_with('/tmp/not_exist_file_2.txt', mode='w')
```

# 参考
- 公式ページ
    - [unittest.mock --- モックオブジェクトライブラリ](https://docs.python.org/ja/3/library/unittest.mock.html)
    - [unittest.mock --- 入門](https://docs.python.org/ja/3/library/unittest.mock-examples.html)
[AWS][EC2] EC2でWEBサーバを立ち上げる

# はじめに
AWSの勉強として、とりあえずEC2をWEBサーバとして立ち上げてブラウザに「Hello World!」を出力してみます。

# アウトライン
1. EC2インスタンスを新規に立ち上げる
2. EC2インスタンスにSSH接続する
3. EC2インスタンスにApacheをインストールする
4. Apache内にindex.htmlを作成する
5. ブラウザで確認する

# SSHコマンドおさらい
- ルートユーザに移動。インストール操作を可能にする。

```
sudo su -
```

- ソフトウェアの更新状況を確認する

```
yum update -y
```

- サーバにApachをインストールする 

```
yum install httpd -y
```

- Apacheを立ち上げる

```
service httpd start
```

- フォルダ遷移
  - htmlフォルダは `/var/www/html`

```
cd
```  

- ファイル、ディレクトリの情報を表示する
  - ディレクトリ内で一覧を表示するのによく使う

```
ls
```

- 今回index.htmlファイルを作成、編集するのにvimを使います

```
vim
```

- Apacheを再度立ち上げる

```
service htttpd restart
```
  

# Vim操作おさらい
- 新規作成
  - `$ vim ファイルパス`
  - 存在しないファイルを指定すると、新規作成
- 編集開始
  - `:i`
  - insert
- 編集終了
  - `escキー`
  - コマンド入力モードに戻る
- 上書き保存
  - `:w`
  - !をつけると強制上書き
- 名前を付けて保存
  - `:w ファイルパス`
  - 既に存在する場合はエラー
  - !をつけると強制上書き
- 終了
  - `:q`
  - 未保存の場合はエラー
  - !をつけると強制終了
- Vimを開いている状態で別のファイルを開きたいとき
  - `:e ファイルパス`

# 1. EC2インスタンスを新規に立ち上げる
とりあえずお金かからないような設定でEC2を立ち上げます

#### AMI
- AL2 64bit(x86)

#### インスタンスタイプ
- t2.micro

#### インスタンス詳細設定
- 削除保護の有効化、モニタリングにチェックを入れる
- それ以外はとりあえずデフォルトの設定で
- 本来はVPCを作成してからEC2を配置します `TODO 後述記事へのリンク`

#### ストレージの追加
- 今回はデフォルトの汎用SSDを使用する

#### タグの追加
- 名前ぐらい登録しておきましょう
- WEBサーバなので
  - キー: name
  - 値: web-1a `TODO さすがに名前変えた方がいいかも`
- ビジネス利用を想定して
  - キー: department
  - 値: development

#### セキュリティグループの設定
- アクセス方式、アクセス制御について設定するところです
- デフォルトで設定されているSSHに加えてHTTP、HTTPSを追加します
- IP指定もできるが、今回はフルオープン(オール0)で

#### キーペア
- 既存で作成してたらそれで
- 既存で作成していない場合は。。。`TODO キーペア作成についての記事へリンク`

# 2. EC2インスタンスにSSH接続する
- ターミナル使ってアクセスしていきます

```
$ ssh ec2-user@パブリックIP -i 秘密鍵ファイルパス -p 22
```

- 毎回コマンドで打つのはめんどうなので `~/.ssh/config` へ以下を追記しましょう

```
    Host 好きな名前
    HostName パブリックIP
    User ec2-user
    IdentityFile 秘密鍵ファイルパス
    Port 22
    TCPKeepAlive yes
    IdentitiesOnly yes
```

```
$ ssh 好きな名前
```
で接続できるはず。

# 3. EC2インスタンスにApacheをインストールする
- ルートユーザに移動します

```
$ sudo su -
```

- ソフトウェア更新状況を確認します(アップデートが必要なソフトウェアの有無を確認しています)

```
$ yum update -y
```

```
yumとは
Linuxに入っているパッケージソフトウェアの管理を行うコマンド
```

- Apacheをインストールする

```
yum install httpd -y
```

```
Apacheとは
WEBサーバソフトウェア(HTTPサーバ)
```

- Apacheを起動する

```
service httpd start
```

# 4. Apache内にindex.htmlを作成する
- htmlフォルダに移動する

```
cd /var/www/html
```

- index.htmlを作成する

```
vim index.html
```

- index.html内に以下を記載して保存する

```
<html><h1>Hello World!</h1></html>
```

- Apacheをリスタートする

```
service httpd restart
```

# 5. ブラウザで確認する
- パブリックIPをURLに貼り付けて「Hello World!」が出力されていれば成功です:clap:
[AWS][EC2] Elastic IPの設定

# はじめに
Elastic IPアドレスをEC2に設定してみます。

# なぜElastic IPを設定するのか
- Elastic IPを設定していないEC2インスタンスを一度停止して、再度起動するとパブリックIPが変わってしまいます
- IPアドレスが変わってしまうとアプリケーション間でIPアドレスをキーに連携したいときなどに困ります
- そのときに使用するのがElastic IPアドレス
- Elastic IPは静的なIPアドレスです

# アウトライン
1. Elastic IPの取得
2. EC2インスタンスへElastic IPを関連づける
3. Elastic IPの解放

# 1. Elastic IPの取得
- Elastic IPを設定したいEC2インスタンスを停止します
- Elastic IP => 新しいアドレスの割り当て からElastic IPアドレスを取得します

# 2. EC2インスタンスへElastic IPを関連づける
- アクション => アドレスの関連付け から対象EC2インスタンスに関連付けを行います

# 3. Elastic IPの解放
- Elastic IP => アクション => 関連付けの解除
- <p class="alert">**警告** Elastic IPは取得して使用するのは無料だが、取得したが使わない場合に料金が発生します</p>
- なので関連付けを解除したら、アドレス解放を行います
- アクション => アドレスの解放
[AWS][EC2] Bashシェルスクリプトによるサーバー設定

# はじめに
Bashというシェルスクリプトを使用してEC2サーバーの設定を行ってみます。

# Bashとは
- コマンド画面でLinuxとやりとりする際に使用するシェルスクリプト
- シェルスクリプト: ユーザーとカーネル(OSの基幹機能)のやりとりに利用される言語のこと
- Bashはシェルスクリプトの一つで、Linuxにおけるシェルスクリプトのデファクトスタンダードになっている
- yumとかもシェルスクリプトの一つ

- EC2サーバーではSSH接続したあとはBashで操作している状況

- **AWSマネジメントコンソールでは、BashによるLinux初期設定の自動実施を設定することが可能です**
  - 起動する際に処理されるBashスクリプトを仕込んでおくことができる
  - Apacheのインストールとか毎回必ず行うような設定は自動実施するようにできる:muscle:


# 作業アウトライン
1. 新規にEC2インスタンスを起動する
2. Bashシェルスクリプトを設定してLinuxの設定を行う
3. Linuxの設定結果を確認する

# 今回設定してみる項目

- ホスト名を変更する
  - デフォルトではIPアドレスがホスト名になっている
  - IPアドレスではわかりづらいので基本は意味のある名前に変更する

```
sed -i 's/^HOSTNAME=[a-zA-Z0-9\.\-]*$/HOSTNAME=任意のホスト名/g'
```

- ネットワークホスト名を変更する

```
/etc/sysconfig/network
hostname '任意のホスト名'
```

- 日本時間をコピー

```
cp /usr/share/zoneinfo/Japan /etc/localtime
```

- サーバーの時間帯を日本時間に設定

```
sed -i 's|^ZONE=[a-zA-Z0-9\.\-\"]*$|ZONE="Asia/Tokyo"/g' /etc/sysconfig/clock
```

- 言語設定をja_JP.UTF-8に設定

```
echo "LANG=ja_JP.UTF-8" > /etc/sysconfig/i18n
```

- ソフトウェアの更新情報の確認

```
sudo yum update -y 
```

- Apacheのインストール

```
sudo yum install httpd -y
```

- Apacheの自動起動設定

```
sudo chkconfig httpd on
```

# 1. 新規にEC2インスタンスを起動する
- EC2インスタンスを作成する
  - 手順 3: インスタンスの詳細の設定の「高度な設定」に以下を記載する

```
#!/bin/bash
# サーバーの設定変更
sed -i 's/^HOSTNAME=[a-zA-Z0-9\.\-]*$/HOSTNAME=任意のホスト名/g' /etc/sysconfig/network
hostname '任意のホスト名'
cp /usr/share/zoneinfo/Japan /etc/localtime
sed -i 's|^ZONE=[a-zA-Z0-9\.\-\"]*$|ZONE="Asia/Tokyo"|g' /etc/sysconfig/clock
echo "LANG=ja_JP.UTF-8" > /etc/sysconfig/i18n
# アパッチのインストール
sudo yum update -y
sudo yum install httpd -y 
sudo chkconfig httpd on
====
```

  - 他の設定項目はデフォルトで:ok_hand:
  - タグはお好みで:information_desk_person_tone1:

# 2. Bashシェルスクリプトを設定してLinuxの設定を行う
- 作成したEC2インスタンスにターミナルでssh接続する

# 3. Linuxの設定結果を確認する
- 接続して、　`[ec2-user@任意のホスト名 ~]$` となっていれば :ok_hand: 
- Apacheインストール
  - `yum list installed | grep httpd` を実行
  - httpdがインストールされていれば :ok_hand:
[AWS][EC2] AMIとSnapshotの活用

# はじめに
AMI(Amazon Machine Image)とSnapshotを利用して、EC2インスタンスをどのように復元したり複製したりするのか説明します

# アウトライン
1. AMIを作成して、新しいインスタンスに反映する
2. 新インスタンスのAMI反映状況を確認する
3. Snapshotを作成して、EBSを複製する
4. EBSの複製結果を確認する

#1. AMIを作成して、新しいインスタンスに反映する
- 対象インスタンスを停止する
- アクション => イメージ => イメージの作成
- 適当なイメージ名を設定してイメージを作成
- AMIでイメージが作成中であることを確認する
- 作成が完了したら選択して「起動」をクリック
- インスタンスタイプの設定画面が表示される
  - AMIの設定は行わなくていいということ
- `ステップ3: インスタンスの詳細設定`で`削除保護の有効化``モニタリング`の項目にチェックを入れる<br>
  `削除保護の有効化について`<br>
  - チェックをいれることでインスタンスを削除するという権限を標準で表示させないようにできる。
  - アクションから削除がいきなりクリックできないようにしてくれる。
  - 基本的に有効化したほうがいい
- `ステップ5: タグの設定`は適当に。
- `ステップ6: セキュリティグループの設定`に関してはイメージ作成元のインスタンスの設定に合わせて設定しておきます
- 設定が完了したら起動します

#2. 新インスタンスのAMI反映状況を確認する
- 作成したインスタンスにSSH接続する
- 作成元インスタンスではシェルスクリプトでApacheをインストールするようにしていたので、Apacheがインストールされているか確認する

```
yum list installed | grep httpd
```

- ApacheインストールされていればAMIが反映されている:thumbsup:
- Apacheがインストールされたインスタンスから作成されたAMIを使用してインスタンスを作成したので、最初からApacheがインストールされている


- 設定済みのインスタンスを複製したい！
  - AMIを利用して効率的にサーバーを構築しよう！！

#3. Snapshotを作成して、EBSを複製する
- 左メニューから`ボリューム`を選択
- `アタッチ済み情報`からどのインスタンスのボリュームか調査する
- 複製元インスタンスのボリュームがわかったら、選択して`アクション` `スナップショットの作成`を選択
- 適当に説明を記入して作成
- 左メニュー`スナップショット`からスナップショットが作成されているか確認する
- 複製先のインスタンスを停止する
- 複製先のインスタンスにアタッチされているボリュームをデタッチする
  - デタッチする前に`アタッチ済み情報`の`dev/xvda`みたいなのをコピーしておく
- 停止、デタッチできたら左メニュー`スナップショット`から対象スナップショットを選択して`アクション` `ボリュームの作成`
- ボリュームができたら複製先インスタンスにアタッチする `アクション` `ボリュームのアタッチ`
- 複製先のインスタンスを指定。デバイスにはコピーしておいたアタッチ済み情報のパスを指定する。
  - デバイスに設定したのは元々のルート。ルートがないとインスタンスが再起動できない。
- 複製先のインスタンスを再起動する

#4. EBSの複製結果を確認する
- 複製先インスタンスにssh接続する
- htmlフォルダを確認する
- index.htmlの中身が正しいことを確認する
- サービスを起動する

```
service httpd start
```

- サーバのパブリックIPアドレスをURLに記載してブラウザに`Hello World!`が表示されることを確認する
[AWS][EC2][EBS] EBS概要

#EBSとは
- Elastic Block Store
- EC2にアタッチされるブロックレベルのストレージサービス

#### 基本
- OSやアプリケーション、データの置き場所など様々な用途で利用される
- 実体はネットワーク接続型ストレージ
- 99.999%の可用性
- サイズは1GB〜16TB
- サイズと利用期間で課金

#### 特徴
- ボリュームデータはAZ内で複数のHWにデフォルトでレプリケートされていて、冗長化は不要
- セキュリティグループによる通信制御対象外であり、全ポートを閉じてもEBSは利用可能
- データは永続的に保存。EC２を削除しても保存される。


- EC2は他AZ内のEBSにはアクセスできない
- 1つのEC2インスタンスに複数のEBSを接続することは可能であるが、1つのEBSに複数のEC2を接続することはできない。
- 他のインスタンスにEBSを付け替えることは可能

###### snapshotについて
- snapshotでバックアップ
- snapshotからEBSを復元する際は別AZに復元することも可能
- snapshotはS3に保存される
- snapshotの２世代目以降は増分データを保存する`増分バックアップ`である(1世代目を削除しても復元可能)
- snapshot作成時にブロックレベルで圧縮して保管するため、圧縮後の容量に対して課金が行われる

- snapshotはリージョンを跨いでも利用可能
  - snapshotを別リージョンに取っておいて障害時に別リージョンから復元することもできる:muscle:

- snapshot作成時はデータ整合性を保つため静止点の設定を推奨している
- 要するにインスタンス停止時や何も処理を行っていないときにsnapshotを取るということ
  - ソフトウェアの機能を利用
  - ファイルシステムの機能を利用
  - バックアップソフトウェアの機能を利用
  - アプリケーションの停止
  - ファイルシステムのアンマウントなど
- 保存期間や世代数は無制限
- 世代管理が必要な場合はAWS CLIやAPI等で自動化できる


##### snapshotとAMI
- Amazon Machine ImageはOS設定のイメージであり、snapshotはストレージのバックアップである
- AMI
  - EC2インスタンスのOS設定などをイメージとして保持して、新規インスタンス設定に転用するもの
- snapshot
  - ストレージ/EBSのその時点の断面のバックアップとして保持するもの
  - ストレージの不k元や複製に利用


#EBSのボリュームタイプ
- ユースケースに応じて性能やコストが異なる5種類のボリュームタイプから選択

## SSD
### 汎用SSD
- ユースケース
  - 仮想デスクトップ
  - 低レイテンシーを要求するアプリ
  - 小〜中規模のデータベース
  - 開発環境
- サイズ
  - 1GB~16TB

### プロビジョンドIOPS SSD
- ユースケース
  - 高いI/O性能に依存するNoSQLやアプリ
  - 10,000IOPSや160MB/s超のワークロード
  - 大規模DB
- サイズ
  - 4GB~16TB

## HDD
### スループット最適化HDD
- ユースケース
  - ビッグデータ処理
  - DWH
  - 大規模なETL処理やログ解析
- サイズ
  - 500GB~16TB
 
### コールドHDD
- ユースケース
  - ログデータなどのアクセス頻度が低いデータ
  - バックアップやアーカイブ
- サイズ
  - 500GB~16TB


## マグネティック(Magnetic)
- ユースケース
  - 旧世代のボリュームで基本利用しない
  - データへのアクセス頻度が低いワークロード
- サイズ
  - 1GB~1TB

# インスタンスストア
- EC2で利用できるストレージはインスタンスストアとEBSの2タイプ
- インスタンスストアは一時的なデータしか保持できないため、通常はEBSを使用する

#### インスタンスストア
- ホストコンピュータに内臓されたディスク
- EC2と分けることはできないブロックレベルの物理ストレージ
- **EC2の一時的なデータが保持**され、EC2の停止・終了と共にクリアされる
- 無料

#### EBS
- ネットワークで接続されたブロックレベルのストレージ
- EC2からは独立している
- EC2をTerminateしてもEBSは保持可能
- snapshotをS3に保持可能
- 別途EBS料金がかかる
laravelでgazzleを使う


## 1.目的
外部のwebAPIをサーバーサイドで一旦取得した後に、そのAPIを叩けるようにしてみる。
忘備録です。

## 2.内容
gazzleをインストール

```
$ composer require guzzlehttp/guzzle
```

Controllerは以下のように実装。

```php:SampleController
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use GuzzleHttp\Client;

class SampleController extends Controller
{

    public function getSampleFromApi(Request $request)
    {

        //叩きたいAPIを持ってくる
        $base_url = 'https://~~~';

        $guzzleClient = new Client();
        $res = $guzzleClient->get($base_url);
        $data = json_decode($res->getBody(),true);
        return $data;
    }
}

```

apiなのでapi.phpに記述。

```php:routes/api.php
Route::get("/sample", "SampleController@getSampleFromApi")->name('sample');
```

ローカルなら、以下のような形で叩いてみる。
http://localhost:8000/api/sample
RaspberryPi4の環境構築と設定 

## はじめに
今回の環境構築に使用したものリスト
- [Raspberry Pi 4 Model B](https://www.raspberrypi.org/products/raspberry-pi-4-model-b/)
- 32 GBのMicro SDカード [Toshiba 32GB](https://www.amazon.co.jp/TOSHIBA-%E6%9D%B1%E8%8A%9D-microSDHC%E3%82%AB%E3%83%BC%E3%83%89-CLASS10-UHS-I%E5%AF%BE%E5%BF%9C/dp/B078NQ5BQ5/ref=sr_1_2?dchild=1&qid=1595489240&s=computers&sr=1-2)
- Micro SDカードが読み込み可能な接続器
- キーボード
- マウス
- USB-Cと接続器 (最大5V/3A)
- Micro HDMI
- モニター

使用するOSはRaspberry Pi OS です。
自分はToshibaの使いましたが他のでも使える可能性があります。ただし相性の問題があるそうなのでご注意してください。
なお、Raspberry Pi用のモニターもありますが、自分はモニターがあったのでMicro HDMIで接続しました。

## RaspberryPi設定の手順
1. Raspberry Piの公式リンクから別のパソコンにRaspberry Pi Imagerを[ダウンロード](https://www.raspberrypi.org/downloads/)
2. Raspberry Pi ImagerからSDカードに書き込み、Raspberry Piに挿入
3. Raspberry Piにキーボード、マウス、Micro HDMIを接続
4. RaspberryPiにUSB-C接続。RaspberryPiはスイッチがないため、電源に接続した瞬間にスイッチONの状態になります
5. 時間がかかりますが、デスクトップ画面が表示されれば完了


## 他の細かい設定
### デフォルトPythonをPython3へ設定
RaspberryPiにはPython2が標準搭載されていますが自分の好みということもあってPython3をデフォルトに設定しました。
1.まずPython3をインストールします

```
$ sudo apt update
$ sudo apt install python3 idle3
```

2.つぎにTerminalを開いて下記のコマンドを入力してください。Python２とPython3のバージョンが確認できます。

```
$ python --version
Python 2.7.16
$ python3 --version
Python 3.7.3
```

3.python --versionと入力した際にPython2のバージョンが出てきたのが確認されました。今回はupdate-alterntivesというコマンドを使用しPythonのバージョンを選択することができるようにします。

```
$ sudo update-alternatives --install /usr/bin/python python /usr/bin/python2.7 1
$ sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.7 2
```

4.これでPythonの優先度を確認することができます

```
$ sudo update-alternatives --list python
```

5.最後にPythonのバージョンを変更します

```
$ sudo update-alternatives --config python
```


### ライブラリのインストール
sodapy、pandas、matplotlibのライブラリがほしかったため、以下のコマンドを実行しました

```
$ pip install sodapy
$ pip install pandas
$ pip install matplotlib
```

補足情報ですが、Python２の状態でインストールするとPython3の状態で使用することができません。
簡単レシート印刷 receiptline でサーマルロール紙に印刷してみた

日本発のオープンソース receiptline でレシート印刷に少しずつトライしています。
[前回](https://qiita.com/dopperi46/items/6043b936d28f6adf8cf4)まで開発ツールと仮想プリンターを利用していましたが、今回はいよいよ実機を使った印刷です。

![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669512/6527e949-12fc-d37f-869d-90e53ea4d7d4.png)

# レシートプリンター

落札に成功したレシートプリンターです。LAN 接続に対応しています。

## TM-T88V

海外旅行へ行くとレジでこれの黒色モデルをよく見かけるような気がします。
新品だと結構なお値段ですが、かなり使い込まれた中古品なので格安で入手。
それでも不具合なく現役バリバリで高速。お値段以上の耐久性はあると思います。

![02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669512/058e4e64-0737-9796-794c-83cb548b264c.jpeg)

## mC-Print3

タブレット POS 向けのコンパクトなモデル。iPad とマッチするデザインです。
個人商店の需要があるようで、ネットオークションやフリマアプリでの相場は高いです。
ファームウェアを更新すれば Lightning ケーブル 1 本で印刷と充電と通信ができるとのこと。

![03.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669512/13cc58d3-45ef-02a6-0dc3-bde6cff4de70.jpeg)

## サーマルロール紙

アマゾンでレジロール紙をあわてて購入。忘れちゃいけない消耗品。
個数の少ないものを選んだ結果、純正の高保存タイプになりました。高級品？
色褪せしにくい高保存タイプは ATM などで使われているようです。

![04.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669512/fced0d89-5d77-e927-6808-6166671b037d.jpeg)

# printers.json の設定

レシートプリンターを LAN に接続。IP アドレスは設定済み。
`printers.json` にプリンターの情報を設定します。
プリンター ID として使える文字は英数字とアンダースコアです。

|プリンター ID|IP : ポート|桁数|言語|用紙排出|出力データ|
|:---|:---|---:|:---|:---|:---|
|tm_t88v|192.168.1.2:9100|42|日本語|上方向 &#x2934;|ESC/POS|
|mc_print3|192.168.1.3:9100|48|日本語|前方向 &#x2935;|StarPRNT|

```json:printers.json
{
    "tm_t88v": {
        "host": "192.168.1.2",
        "port": 9100,
        "cpl": 42,
        "encoding": "cp932",
        "gamma": 1.8,
        "upsideDown": false,
        "command": "escpos"
    },
    "mc_print3": {
        "host": "192.168.1.3",
        "port": 9100,
        "cpl": 48,
        "encoding": "cp932",
        "gamma": 1.8,
        "upsideDown": true,
        "command": "starmbcs"
    }
}
```

# テスト印刷

開発ツールのテスト印刷機能を使って、過去記事のデータをサーマルロール紙に印刷しました。
TM-T88V は 42 桁 (180 dpi)、mC-Print3 は 48 桁 (203 dpi) ですが、どちらも印刷できています。
ただ、印刷の向きを反対にしているので、上下の余白は異なります。

![05.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669512/b99463c6-3a25-96d7-6627-99f10db14cd2.jpeg)

## TM-T88V

![06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669512/6bea3d01-b5bc-c074-bb9d-32d55781311d.png)

![07.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669512/55e3809c-38d0-c173-6485-6dfab0d42062.jpeg)

![08.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669512/feb880e0-e07a-aeff-67d5-659314dc2111.jpeg)

## mC-Print3

![09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669512/b66621d3-f581-0da6-fe47-506e8acbf259.png)

![10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669512/19b9833b-c642-56ed-834f-4fee321b3e4b.jpeg)

![11.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669512/6b721f33-83c1-c782-90c4-2f06add1a72e.jpeg)

次回は receiptline シリーズ最終回？変換 API を使ってアプリを作ります！
ニューラルネットワークの学習

##ニューラルネットワークのモチベーション
結論、データから学習できることが最大の強みである.重みパラメタを手動で決定するのではなく自動でデータから学習してくれるのがNNのいいところ（すごいところ）.  

##でも自動でってどう言う風に？？
損失関数という指標を用いてパラメタを更新していき最適なパラメタを求める.損失関数とは一言で言えば、最適なパラメタを見つけるための指標である.  
また損失関数はNNの性能の悪さを表す.つまり、「教師データに対して現在のNNがどれほど優秀でないか」を示す.　　
機械学習の問題はデータを教師データと訓練データに分けて、このうち訓練データを用いて学習を行う.ここで言う学習とは、「訓練データに関する損失関数を求めてその値をできるだけ小さくするようにパラメタを探す」と言うことである.  

実用的には、最適なパラメタと言うのは損失関数が最小値を取るときのパラメタの値のことを言う.
RubyでFile::Statを使って情報引き出す

メモです。
File::Statはファイルの情報を格納したオブジェクトのクラスです。また、ファイルの所有ユーザ・グループを表示させるためにetc使います。

[class File::Stat \(Ruby 2\.7\.0 リファレンスマニュアル\)](https://docs.ruby-lang.org/ja/latest/class/File=3a=3aStat.html)

[module Etc \(Ruby 2\.7\.0 リファレンスマニュアル\)](https://docs.ruby-lang.org/ja/latest/class/Etc.html)


```ruby 
require "etc"
stat = File::Stat.new("aaa.rb")

puts stat.uid #=> 501
puts stat.gid #=> 20
puts stat.size #=> 1738
puts stat.mtime #=> 2020-07-23 16:46:50.584154183 +0900
puts stat.uid #=> 501
puts Etc.getpwuid(stat.uid).name #=> uetennis
puts Etc.getgrgid(stat.gid).name #=> staff
puts File.basename("aaa.rb") #=> aaa.rb

```
パレットと屋内地図データ

# パレット
国連ベクトルタイルツールキットでベクトルタイルのスタイルを作るときに、私は style.json を直接書くこともしなければ、グラフィカルなツールも使いません。

HOCON でレイヤごとにスタイルを書いて include する形をとっています。

スタイルを書くときに煩雑になり、また手抜きの温床になりがちなのが色の指定です。色の指定にも include を使うことで、よく統制されたパレットを使いやすくなると思いました。

ディスプレイや紙と異なるのですから、ディスプレイに合わせて設計されたパレットを使うべきです。私は 2014 Material Design color palette を使うことが多いです。

## Material Design color palette の Mapbox Style / HOCON 実装

スタイルの記述が、次のように実現できるようにします。

```hocon
line-color: include "https://unvt.github.io/mat/orange-300"
```

その実装を https://github.com/unvt/mat に置きました。

# 屋内地図データのベクトルタイル化
屋内地図データのベクトルタイル化をたまたま手掛けていたので、上記のパレットを使用してみました。例えば、次のような形で記載しています。

```hocon
id: drawing
type: line
source: v
source-layer: drawing
paint: {
  line-color: include "https://unvt.github.io/mat/blue-gray-300"
}
```

レポジトリは https://github.com/optgeo/technopolis で、テストサイトは https://optgeo.github.io/technopolis です。

上空にフロアの上下関係を表現しています。

<img width="896" alt="上空に表現したフロアの上下関係" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102082/6dc397f0-1869-815f-e862-5a5b5df4c712.jpeg">

地上には、図面を素直に置いています。

<img width="898" alt="地上に素直に置いた図面" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102082/740829d5-c8fb-5858-1792-e8beae5eed0c.jpeg">
Javaで実行する複数ブラウザ対応（Chrome、IE、Firefox）Seleniumサンプルアプリを作成しました



# 概要
selenium関連の記事は豊富にありますが、今回はWindowsOSでとりあえずサクッとマルチブラウザテスト等で流用できるようなサンプルアプリを作成しました
※Chrome、IE、FireFoxで実施できるようにしています
※eclipseから実行の想定です

### 実行環境
Windows10 Pro
Eclipse IDE for Enterprise Java Developers
JavaSE 11

各ブラウザバージョン
Chrome：84.0.4147
Firefox：78.0.2
InternetExplorer：11.959.18　　　　

# サンプルアプリ使用方法

###１．サンプルアプリ配置

#### サンプルアプリをClone

・下記URLからCloneしeclipseのworkspaceフォルダに配置
https://github.com/ZumWalt22/seleniumExp.git

・eclipseからCloneしたプロジェクトをインポート
ファイル>インポート>一般>既存プロジェクトをワークスペースへ　でCloneしたディレクトリを選択しプロジェクトをインポート
※Firefoxドライバはフルパス指定でないと動作しないため、適宜修正（seleniumEx.java 113行目） 
　サンプルコードは「C:/pleiades/workspace/」にプロジェクト「seleniumExp」をCloneしている想定で記述

・IEブラウザ事前設定
IEで実行する場合、ブラウザで事前に以下の設定を実施してください
インターネットのオプション→セキュリティタブ
インターネット、ローカルイントラネット、信用済みサイト、制限付きサイトの「保護モードを有効にする(Internet Explorerの再起動が必要)」にチェックを入れる
「拡張保護モードを有効にする」チェックボックスを外す	

###２．サンプルアプリ実行

##### 1)eclipseからサンプルアプリを実行
プロジェクト・エクスプローラーを右クリック、「実行」>「1.Javaアプリケーションを実行」をクリック

##### 2)実行対象ブラウザを選択
コマンドプロンプトで、下記のように、どのブラウザで実行するかが聞かれるので
動かしたいブラウザの番号を入力しEnterキーを押下

```
input target test browser 0:Chrome 1:IE 2:FireFox >
```
・Chromeで動かす場合「0」を入力
・IEで動かす場合「1」を入力
・FireFoxで動かす場合「2」を入力


##### 3) 指定のブラウザが立ち上がりseleniumでブラウザが自動実行される

Googleのサイトが立ち上がり「selenium」文字列が検索ボックスに設定され、検索が実行されるサンプルが動作します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172093/6127cc43-e571-078a-2611-4f042de29e63.png)

# ドライバライブラリの変更方法
selenumサーバ、各ブラウザのドライバが変わった場合、Windows以外のOSで実施する場合
下記情報を参考にして適宜ファイルを置き換えてください

###１．seleniumサーバ
下記のURLからダウンロード
https://www.selenium.dev/downloads/
「Selenium Server (Grid)」のリンクをクリックしダウンロード
※当サンプルアプリでは「Latest stable version 3.141.59」をダウンロード
jarをseleniumExpプロジェクトの下記の「lib」>「jar」フォルダ配下に配置
Javaのビルドパス>ライブラリ　から「JARの追加」で配置したJARを追加

###２．各ブラウザドライバ
#####・Chromeドライバ
下記のURLからドライバをダウンロード
https://sites.google.com/a/chromium.org/chromedriver/downloads
※当サンプルアプリでは「 ChromeDriver 83.0.4103.39」　chromedriver_win32.zip　をダウンロード
seleniumExpプロジェクトの下記の「selenium」>「chrome」フォルダ配下に任意のフォルダ名（バージョン等）の名称を付け配置

「seleniumEx.java」ファイルの78行目、下記のメソッドの第二引数のパスを上記配置場所のパスに修正
System.setProperty("webdriver.chrome.driver", "selenium/chrome/83.0/chromedriver.exe");

#####・IEドライバ
下記のURLからドライバをダウンロード
https://www.selenium.dev/downloads/
※当サンプルアプリでは「The Internet Explorer Driver Server」「Download version 3.150.1 」　IEDriverServer_Win32_3.150.1.zipをダウンロード
seleniumExpプロジェクトの下記の「selenium」>「ie」フォルダ配下に任意のフォルダ名（バージョン等）の名称を付け配置

「seleniumEx.java」ファイルの99行目、下記のメソッドの第二引数のパスを上記配置場所のパスに修正
System.setProperty("webdriver.ie.driver", "selenium/ie/3.15/IEDriverServer.exe");

#####・Firefoxドライバ
下記のURLからドライバをダウンロード
https://github.com/mozilla/geckodriver/releases
※当サンプルアプリでは　geckodriver-v0.26.0-win32.zip　をダウンロード　
seleniumExpプロジェクトの下記の「selenium」>「firefox」フォルダ配下に任意のフォルダ名（バージョン等）の名称を付け配置

「seleniumEx.java」ファイルの113行目、下記のメソッドの第二引数のパスを上記配置場所のパスに修正
System.setProperty("webdriver.gecko.driver", "C:/pleiades/workspace/seleniumExp/selenium/firefox/0.26/geckodriver.exe");
※FireFoxのドライバ配置場所はフルパスで記述する必要あり

# 参考資料

Selenium2をIEで起動させてみる。
https://qiita.com/tsuttie/items/372f5d4cad37650711f1

Selenium使ってみたら意外と簡単に始められた
https://qiita.com/kazokmr/items/0dc6b67e5a90ffc27db6
【swift】 ビルドができず、unable to open fileのエラー


## 1.状況

git cloneしてswiftのコーディングをしようとしたが、
ファイルが開かず、シミュレーションも起動しない。

<img width="839" alt="スクリーンショット 2020-07-23 16.25.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244070/b7639cce-4bee-6ed6-5188-e1ae4bd12145.png">


```
Showing All Issues
/Documents/practice_swift/Pods/Target Support Files/Pods-todoapp/Pods-todoapp.debug.xcconfig: unable to open file (in target "todoapp" in project "todoapp")
```
## 2.原因
cocoapodsのインストールがなかった。

### cocoapodsとは、
iOSアプリ作成のためのライブラリ管理をしてくれるもの
https://cocoapods.org/


cocoapodsのインストールをします。

```
 $ sudo gem install cocoapods

 $ sudo gem update –system
 $ sudo gem install -n /usr/local/bin cocoapods
 $ pod setup
```

git cloneしたプロジェクトファイルに移動してインストールをします。

```
 $ pod deintegrate
 $ pod install
```


結果は良さそう。DBの役割のRealmもインストールされている。

```
Downloading dependencies
Installing Realm (5.1.0)
Installing RealmSwift (5.1.0)
Generating Pods project
Integrating client project
Pod installation complete! There is 1 dependency from the Podfile and 2 total pods installed.
```

もう一度xcodeでビルディングしてみる
<img width="555" alt="スクリーンショット 2020-07-23 16.36.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244070/93f4a4f3-e121-1c74-7f71-fbfa8762a584.png">


ビルディング成功！やった！
<img width="372" alt="スクリーンショット 2020-07-23 16.38.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244070/236b84b4-bab5-2e88-a4bd-4cd50009b838.png">
システムの信頼性向上技術、フェールソフト、フォールトマスキング、フェールセーフ、フールプルーフ、フォールトトレラント、フェールオーバ

応用情報技術者令和元年秋期 午前問16

システムの信頼性向上技術に関する記述のうち，適切なものはどれか。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/339a30a1-0d71-1bcf-4ef2-ed51993f36a9.png)


**フェールセーフ**
フェールセーフは、システムに不具合や故障が発生したときでも、障害の影響範囲を最小限にとどめ、常に安全を最優先にして制御を行う考え方です。

**フェールソフト**
クラスタ構成のシステムにおいて、あるサーバが動作しなくなった場合でも、他のサーバでアプリケーションを引き継いで機能を提供する。
障害が発生した際に，正常な部分だけを動作させ，全体に支障を来さないようにする。 


**フォールトアボイダンス**
故障が発生したときに対処するのではなく、品質管理などを通じてシステム構成要素の信頼性を高めるシステム。

**フォールトマスキング**
故障が発生したときに、その影響が誤りとなって外部に出ないように訂正するシステム。


補足
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
１、フールプルーフ　foolproof
直訳すると「簡単」となりますが、むしろ「フール」と「プルーフ」に分けた方が本来の意味に近いように思います。 つまり、
**「何も知らない人が使っても大丈夫なように証明されているもの」
  「使用方法を知らない、もしくは間違った使い方をしても大事に至らないような設計」
**のことです。


２、フェイルセーフ　fail-safe　
敗するけど安全？？ 「操作方法を間違ったり、部品が壊れたり、誤作動したりした場合に、危ない方向ではなく、安全な方向へ向かう」ように設計することをいいます。


補足２
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
安全性や信頼性について，次の方針でプログラム設計を行う場合，その方針を表す用語はどれか。

　“不特定多数の人が使用するプログラムには，自分だけが使用するプログラムに比べて，より多くのデータチェックの機能を組み込む。プログラムが処理できるデータの前提条件を文書に書いておくだけでなく，その前提を満たしていないデータが実際に入力されたときは，エラーメッセージを表示して再入力を促すようにプログラムを作る。”

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/0922ad46-c7f0-c949-cd24-c1ecd9991271.png)
　
fool（＝専門家ではない、普通の方）でも使えることを証明できるから、「フールプルーフ」ですね。


**フォールトトレラント（fault tolerant）**は、システムの一部に障害が発生しても全体としては停止することなく稼働を続け、その間に復旧を図るようにシステムを設計する考え方です。これを実現するには各機器を二重構成にし障害発生時には機器の切替えを即座に行える設計であることが条件となります。
※tolerant 寛容な,雅量のある


補足３
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/39d71543-58f4-ed49-5602-3aa6380533cd.png)

ア：フェールセーフ
イ：フォールトトレラント
ウ：フェールソフト
エ：フールプルーフ


結論：AP試験では、必ず出題すると思っておりますね。


ーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
補足
システムの信頼性に関する記述のうち，フェールオーバの説明はどれか。

ア、障害が発生した場合でも，処理やデータを他の処理装置に自動的に引き継ぎ，切替え処理を意識させない。
イ、障害が発生した場合に，それが原因で危険な結果にならないよう，常に安全側の状態にする。
ウ、人間の過失などが原因で予期されない使い方をしても，信頼性や安全性を損なわない。
エ、部品やサブシステムに信頼性の高いものを用いることによって，システム自体の故障発生を極力少なくする。

１、フェールオーバ(failover)は、
主系のシステムで障害が発生したときに、自動的に予備系のシステムに切替えを行うことで、実行中の処理を継ぎ目なく続行する技術、またはそれを実現するシステム構成です。
高い可用性と信頼性が求められるシステムでは、フェールオーバ機能を組込むのが一般的です。


フェールオーバ vs フェールソフト：
・フェールオーバー、
オーバー、超える。なにを超えるのでしょう？
大型旅客機は機長と副操縦士の二人が操縦しています。機長が突然気を失ったらどうしましょう？副操縦士が「フェールオーバー」して運転続行します。

このようにフェールが起きた時にでも、完全にそれを補完する事ができ、その補完状態になることをフェールオーバーというわけです。

・フェールソフト、
ソフト、柔らかさです。
空中で飛行機のエンジンが片方止まったとしましょう。ここで全機能を停止させてしまうと不時着もできません。そこで故障したほうのエンジンだけは燃料遮断しもう片方のエンジンだけで飛べる様に設計されています。

このようにフェールがおきた時にでも、なんとか動作を継続させるという設計がフェールソフトというわけです。


参照：
https://www.sc-siken.com/kakomon/28_haru/am2_22.html

https://www.itpassportsiken.com/kakomon/21_haru/q65.html

フールプルーフ[foolproof]とフェイルセーフ[fail-safe]
https://www.i-learning.jp/topics/column/useful/foolproof.html

フェールオーバ
https://qiita.com/nanatsu/items/e900841a9f678fa07296#9-%E3%83%95%E3%82%A9%E3%83%BC%E3%83%AB%E3%83%90%E3%83%83%E3%82%AFfall-back


https://www.ap-siken.com/kakomon/23_toku/q16.html#:~:text=%E3%83%95%E3%82%A7%E3%83%BC%E3%83%AB%E3%82%AA%E3%83%BC%E3%83%90(failover)%E3%81%AF%E3%80%81%E4%B8%BB,%E5%AE%9F%E7%8F%BE%E3%81%99%E3%82%8B%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E6%A7%8B%E6%88%90%E3%81%A7%E3%81%99%E3%80%82

フェールオーバ vs フェールソフト
https://kanasys.com/tech/786
React Hooks Error Context

:::note warn
この実装はアンチパターンになります。
Contextにstateを持つと、state更新時にContext以下のすべてのコンポーネントで再描画が起こります。
:::

----
こちらの方の記事の実装にIF定義を追加したもの。
[React で side effect のエラーハンドリング](https://qiita.com/maaaashin324/items/e0fb43be6ccf4b950eae)


```tsx
import React, {createContext, useContext, useState} from "react";

interface ErrorContextInterface {
    hasError: boolean,
    userMessage: string | null,
    error: Error | null,
    setContextError: (userMessage: string, error: Error) => void,
    setContextErrorDone: () => void
}

const ErrorContext = createContext<ErrorContextInterface>({
    hasError: false,
    userMessage: null,
    error: null,
    setContextError: (userMessage: string, error: Error) => {
    },
    setContextErrorDone: () => {
    },
});

export const ErrorProvider: React.FC<object> = props => {
    const [hasError, setHasError] = useState<boolean>(false);
    const [userMessage, setUserMessage] = useState<string | null>(null);
    const [error, setError] = useState<Error | null>(null);

    const setContextError = (userMessage: string, error: Error) => {
        setUserMessage(userMessage);
        setError(error);
        setHasError(true);
    };

    const setContextErrorDone = () => {
        setUserMessage(null);
        setError(null);
        setHasError(false);
    };

    return (
        <ErrorContext.Provider
            value={{hasError, userMessage, error, setContextError, setContextErrorDone}}
            {...props}
        />
    );
};

export const useError = () => {
    const context = useContext(ErrorContext)

    return context
}
```
Vim 入門 【備忘録】

#はじめに
改めて、Vimを勉強したので、備忘録に書きます。

#Vimのモード

##ノーマルモード
開いた際のモード

##入力モード
小文字のiを入力で入る
下記に-- INSERT --と表示される

エディタと同じで、文字を挿入可能

出る際にはESCキーを入力
→ノーマルモードに入る

##コマンドモード
:を入力して、入る
→更にいくつかのコマンドを入力できる

出る際にはESCキーを入力

###q エディタの終了
→!をつけると強制終了

###w 変更の保存
→名前を付けて保存する場合は、wの後に名前をつける
例) :w test.txt

###e 他のファイルを開く


##ビジュアルモード
vを入力すると入る
→文字単位での選択ができる
　その範囲に対して、処理を行える
Vを入力すると入る
→行列単位での選択ができる

Ctrl + V
→矩形選択ができる

全選択 Vを入力後、Gを入力


出る際にはESCキーを入力

##移動系コマンド
ノーマルモードから利用可能

###gg　先頭にカーソル移動
###G 　一番、最後までカーソル移動


###Ctrl + f 　1画面下に移動する
###Ctrl + b 　1画面上に移動する

###w 単語単位で前に移動
###b 単語単位で後ろに移動

###^ 行頭に移動
###$ 行末に移動

###f　指定文字まで移動
→fの後に移動したい文字を入力
例) :fu
→カーソル位置からuの文字が一番最初に出てくる場所へ移動
→また、;を入力すると次の指定文字に移動する

###% {　に対応した } へ移動する
→{　の箇所の上にカーソルがある際に%を押すと対応した } に移動する

##編集系コマンド
ノーマルモードから入れる
###カット
xを入力すると文字単位でカット

ddを入力すると行単位でカット
→複数行をカットしたい場合、ddの前に数値を入力
例)4dd
→カーソル位置とカーソル位置から下3行をカット

###貼り付け
pを入力すると貼り付け

###コピー
yyを入力すると行単位でコピー

##検索系コマンド
ノーマルモードから入れる(/を入力する)

###n　下方向に検索
###N　上方向に検索

###*と#　今カーソルがある位置の単語を検索(上/下)

##置換コマンド
ノーマルモードから入れる

###:s/置換したい単語/置換後の単語/
→1箇所、置換する

###:s/置換したい単語/置換後の単語/g
→カーソルのある行の該当箇所、すべてを置換する

##取消コマンド

###u  元に戻す
→何度でも戻すことが可能

###CTRL + r リドゥ(もとに戻した処理の取消)

##直前の操作を繰り返す
ノーマルモードで.を入力で直前のコマンドを実行する

##インデントを揃える
ノーマルモードから=を入力すると行単位でインデントが揃う

##矩形選択後に編集する
ノーマルモードからCtrl + v
↓
選択する
↓
shift + i
↓
編集する
単一責任の原則 - Single responsibility princple -

お久しぶりです。せしまるです。

今回はSOLID原則の一つ「単一責任の原則」について書いていきます。
いつも通り（？）私のための備忘録('ω')

# 単一責任の原則 is なに

1つのクラス・メソッド（関数）等に、変更する理由が2つ以上あってはダメ！ということ。

例えば、2つの役割を持ったクラスがあるとする。（役割A、役割B）
役割Aに何かしらの変更があった場合、クラスに変更が発生する。
役割Bに何かしらの変更があった場合も、クラスに変更が発生する。

この場合、クラスを変更する理由は
・役割Aに変更があった時
・役割Bに変更があった時

つまり変更する理由が２つになってしまう。
→🙅🙅🙅🙅🙅🙅🙅🙅

以下のような店員クラスがあるとする。

```C#:Clerk.cs:
public class Clerk
{
    // 店員の名前
    public string Name()
    {
        return "せしまる";
    }

    // 店員がいるお店の名前
    public string StoreName()
    {
        return "せしまるラーメン";
    }

    // 料理する
    public string Cook()
    {
        return "葱ラーメンおまち！";
    }
}
```

名前を聞いたら答えてくれる、どこのお店の人なのかも答えてくれる、そしてラーメンを作ってくれる！

これくらい規模が小さいと特に気にすることはないかもですが・・・

え？葱ラーメンじゃなくて味噌ラーメンになった？
Cook()メソッドに変更が入りますね。

え？お店の名前が変わった？
StoreName()メソッドに変更が入りますね。

この時点で変更する理由が二つですね～

# なんでだめ？

もし役割が複数ある場合に変更すると…
変更点の差分とか見たときに「なんでここ変更したんだ？」ってなるし、もしかしたら「なんかほかの処理がおかしくなった！」ということになって、変更したことによる変更が起きてしまうかも…(´・ω・｀)

# 役割を1つに…

では店員クラスを役割で分割してみましょう

```C#:Clerk.cs:
// 店員クラス
public class Clerk
{
    // 店員の名前
    public string Name()
    {
        return "せしまる";
    }

    // 店員がいるお店の名前
    public string StoreName(IStore store)
    {
        return store.GetName();
    }

    // 料理する
    public string Cook(ICuisine cuisine)
    {
        return $"{cuisine.GetName()}おまち!";
    }
}
```

```C#:Interface
public interface IStore
{
    string GetName();
}

public interface ICuisine
{
    string GetName();
}
```

```C#:Stores
public class SeshimaruRamen: IStore
{
    public string GetName()
    {
        return "せしまるラーメン";
    } 
}

public class SeshikoRamen: IStore
{
    public string GetName()
    {
        return "せし子ラーメン";
    }
}
```

```C#:Cuisines
public class GreenOnionRamen: ICuisine
{
    public string GetName()
    {
        return "葱ラーメン";
    }
}

public class MisoRamen: ICuisine
{
    public string GetName()
    {
        return "味噌ラーメン";
    }
}
```

この状態なら、お店の名前が変わってもお店を増やせば店員クラスには変更が入りませんね。

以上！

# 余談

題材にした店員とかが悪すぎた
Orbtkでのrender::RenderPipelineメモ

当方Rustはじめて2ヶ月なので間違いあれば優しく槍投げていただけると助かります。

#render::RenderPipelineのdraw()をGUIに対応させるには
ボタンクリックなどでcanvasの内容を変更したりする際には以下が必要
・アクション管理担当のenum
・描画管理担当のstruct
・状態管理担当のstruct


##アクション管理担当のenum
flutter風にGUIを記述している箇所のマウスクリックなどのイベント時に受け渡したいのを用意しておく

```
#[derive(Debug, Copy, Clone)]
enum Action {
  // Entityは渡したい値
  ValueChanged(Entity),
  PushButton,
}
```


##描画管理担当のstruct

```
#[derive(Clone, PartialEq, Pipeline, Default)]
struct 描画管理担当構造体名 {
// 保持したい値をCellで包む
    変数名: Cell<型>
}
```

```
impl 描画管理担当構造体名 {
   fn set_変数名(&self, val: 型) {
       self.変数名.set(val);
   }
}
```

```
impl render::RenderPipeline for Graphic2DPipeline {
    fn draw(&self, render_target: &mut render::RenderTarget) {
        // self.test.get()で使える
    }
}
```

##状態管理担当のstruct

```
#[derive(Default, AsAny)]
pub struct MainViewState {
  action: Option<Action>,
  変数名: 型,
}
```
もしくはimpl Default for MainViewStateでdefault()処理を用意する

```
impl MainViewState {
  // GUI処理記述部分からアクションを受け取る
  fn set_action(&mut self, action: impl Into<Option<Action>>) {
    self.action = action.into();
  }
}
```

```
impl State for MainViewState {
  fn update(&mut self, _: &mut Registry, ctx: &mut Context<'_>) {
    if let Some(action) = self.action {
      match action {
        Action::PushButton => {
          // アクションに対応した処理。状態管理担当クラスの変数を更新したりする。
        }
        Action::ValueChanged(entity) => {
          // アクションに対応した処理。状態管理担当クラスの変数を更新したりする。
        }
        _ => (),
      };
    }
    if let Some(canvas) = ctx
      .widget()
      .get_mut::<RenderPipeline>("render_pipeline")
      .0
      .as_any()
      .downcast_ref::<Graphic2DPipeline>()
    {
      // 状態管理担当structの変数を描画担当structに反映させる
      canvas.set_変数名(self.変数名);
    } else {
      println!("missing canvas");
    }

    // 画面更新毎に処理が行われるのでアクションを無効化する
    self.action = None;
  }
}
```


##GUI記述箇所

``` 
impl Template for MainView {
  fn template(self, id: Entity, ctx: &mut BuildContext) -> Self {
    self
      .name("MainView")
      .render_pipeline(RenderPipeline(Box::new(Graphic2DPipeline::default())))
      // canvas
      .child(
        Canvas::create()
          .width(640.0)
          .height(800.0)
          .render_pipeline(id)
          .build(ctx),
      )
      // (その他のGUIなど)
```

###アクション処理部分

```
.on_click(move |states, _| {
                states
                  .get_mut::<MainViewState>(id)
                  .set_action(Action::PushButton);
                true
              })
```


以上

###ちなみに
render::RenderPipelineのdraw()処理は
https://developer.mozilla.org/ja/docs/Web/API/CanvasRenderingContext2D
を参考にすれば良さそう。pathを書いてからfill() or stroke()
【JavaScript入門】ダイアログ

## はじめに
Webサイトを作成する際、
①　サイトにアクセスしたとき、何か警告メッセージを表示したい
②　登録フォーム・ログアウト処理など...ミスクリック防止の為に確認画面を表示したい
③　特定の人しかアクセスできないサイトへ遷移するボタンを設置したい
と思うことあると思います。
今回は、そんな機能についてご紹介します。

## ① 警告メッセージを表示するalert関数
まず、警告を出したい場合は、alert関数を使います。

```html:alert関数
<script>
  alert('Hello');
</script>
```

このalert関数は、ただ文字列を表示するのみで、OKを押したら処理を続行します。

## ② 確認ダイアログの表示するconfirm関数
次に、処理を続行するかどうか選択させる場合は、confirm関数を使います。

```html:confirm関数
<form name="logout_form">
  <input type="submit" name="logout" value="ログアウト">
</form>

<script>
  // logout_formにあるlogoutがクリックされたとき
  document.logout_form.logout.addEventListener('click', function(){
    var result = confirm('本当にログアウトしますか？');
    if(result){
      // trueの処理(OKを選択した場合)
    }else{
      // falseの処理(キャンセルを選択した場合)
    }
  })
</script>
```

## ③ 文字を入力させるprompt関数
最後に、文字列の入力を促す際は、prompt関数を使います。

```html:prompt関数
<form name="secret_form">
  <label>こちらは身内専用です</label>
  <input type="button" name="secret" value="身内専用"> 
</form>
<script>
  // secret_formにあるsecretをクリックした場合
  document.secret_form.secret.addEventListener('click', function(){
    // 第二引数は初期値
    var result = prompt('パスワードを入力してください', 'テスト');
    if(result === "password"){
      // trueの処理(passwordと入力された場合)
    }else{
      // falseの処理(入力されたものが誤り・キャンセルを押した場合)
      alert("パスワードが違います。");
    }
  })
</script>
```

## 参考
- [addEventListenerとは](https://developer.mozilla.org/ja/docs/Web/API/EventTarget/addEventListener)
- [JavaScriptでダイアログを表示：alert(), confirm(), prompt](https://uxmilk.jp/14032)
- [イヌでもわかるJavaScript講座](http://cya.sakura.ne.jp/java/prompt.htm)
PHP覚書

<font color=red><b>この記事はずっと下書きのまま放置していましたが、下書き整理のためそのまま投稿しています。</b></font>

#設定確認
ちょっと確認するぐらいなら `php -i | grep` で。

#動作確認
ちょっと確認するぐらいなら `php -r "echo 'hoge', PHP_EOL";` とかで。
`PHP_EOL` は環境に合わせた改行コードの定数。その他→[定義済みの定数](http://php.net/manual/ja/reserved.constants.php)
1行でやりづらいなら `php -a` で。ファイルの実行は `php hoge.php`。ファイルを作成する際は `<?php` を最初に。

#配列操作
##要素確認
###**in_array**
```php
// in_array は指定の配列の値に対して、配列内に存在すればtrueを返す
php > var_dump(in_array(1, [1, 2, 3]));
php shell code:1:
bool(true)

php > var_dump(in_array(0, [1, 2, 3]));
php shell code:1:
bool(false)

php > var_dump(in_array(1, [1 => 10, 2 => 20, 3 => 30]));
php shell code:1:
bool(false)

php > var_dump(in_array(10, [1 => 10, 2 => 20, 3 => 30]));
php shell code:1:
bool(true)
```
###**array_key_exists**
```php
// array_key_exists は指定の配列のキーに対して、配列内に存在すればtrueを返す
php > var_dump(array_key_exists(1, [1 => 10, 2 => 20, 3 => 30]));
php shell code:1:
bool(true)

php > var_dump(array_key_exists(10, [1 => 10, 2 => 20, 3 => 30]));
php shell code:1:
bool(false)
```


##追加・上書き
```php
// + では追加はされるが、上書きはされない
php > var_dump(['a' => 1, 'b' => 2] + ['a' => 10, 'c' => 3]);
php shell code:1:
array(3) {
  'a' =>
  int(1)
  'b' =>
  int(2)
  'c' =>
  int(3)
}

// array_mergeなら、追加かつ上書きとなる
php > var_dump(array_merge(['a' => 1, 'b' => 2], ['a' => 10, 'c' => 3]));
php shell code:1:
array(3) {
  'a' =>
  int(10)
  'b' =>
  int(2)
  'c' =>
  int(3)
}
```
Powershellでコマンドのエイリアスを作成する

# 内容
コマンド名のエイリアスを設定する

# 方法
例として、Linuxコマンドでいう`grep`コマンドを設定する。(Powershellコマンドでは`Select-String`)
以下のコマンドをPowershell上で実行する。

```Powershell:Powershell
Set-Alias -name grep -value Select-String
```
ATOMのerbファイルでEmmetが効かなくなった時に

初めてQiitaに記事を書きます。
今Railsを学習している所で、エディタはAtomを使っています。
Railsの.html.erbファイルを記述している時にEmmetの機能が効かなくなったので、個人的に解決した方法を残しておきます。

#Atomで、erbファイルを編集する時にEmmetの機能を使いたい

普通のhtmlファイルを編集する時に
nav.box>ul>li*5
のようにすると、tabキーで

```html
<nav class="box">
  <ul>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
  </ul>
</nav>
```
になるのに、erbファイルだと全く効かず、ただインデントが追加されるだけでした。
Atomの記事が少なく解決までに時間がかかったので、個人的に解決した方法を残しておきます。


##Emmetの設定で、 html.erbも読み込めるようにする

Atomを開き、上部タブのAtom > 環境設定 > 設定フォルダを開く　に行きます。<img width="300" alt="スクリーンショット 2020-07-23 15.48.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629679/dc981534-48df-05f3-bfa9-c917dc5c1ebd.png">

開いたページの中の、 .atom > packages > emmet > keymaps >emmet.cson　を開きます。
３７行目に　'tab': 'emmet:expand-abbreviation-with-tab'　とあり、tabキーを押した時に対応する言語が36行目にずらっと書いてあります。
<img width="300" alt="スクリーンショット 2020-07-23 15.49.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629679/d3a47e41-8599-50f6-8dee-7baf6d647fed.png">

36行目に、

```
atom-text-editor[data-grammar="text html ruby"]:not([mini])
```

を追加し,保存します。



画面を閉じた後もう一度Atomの環境設定を開き、キーバインドを開きます。
先ほど保存した内容があるので、コピーします。
ボードクリップのマークをクリックでコピーできます。
<img width="959" alt="スクリーンショット 2020-07-23 16.04.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629679/46d03b19-e410-876a-1280-098f4a8694d9.png">

上部のAtomタブ > キーマップ　を開き、コピーした内容を貼り付けて保存します。
自分はこれで、erbでもemmetの機能を使えるようになりました。

折角なので、これからも何かあれば投稿していこうと思います。
1分当たりの最大データ処理件数は幾つか

応用情報技術者令和元年秋期 午前問15

1件のデータを処理する際に，読取りには40ミリ秒，CPU処理には30ミリ秒，書込みには50ミリ秒掛かるプログラムがある。このプログラムで，n件目の書込みと並行してn＋1件目のCPU処理とn＋2件目の読取りを実行すると，1分当たりの最大データ処理件数は幾つか。ここで，OSのオーバヘッドは考慮しないものとする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/acd8a3bf-29a3-2eea-7784-ae1e3680655f.png)

並行処理ですが、実は列の観点からみると、読むとCPU処理と書くは並行では、最大の書く時間以内で、１件データ処理できるですね。
なので、１分/50ミリ秒が答えです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/cdf8551b-6f6b-84b6-6207-53112809fe44.png)
【Automation Anywhere A2019】Excelの基本操作/高度な操作でセルを取得したときの値の違いに注意

RPAツールのAutomation Anywhere A2019では、[Excelファイルを操作するためのパッケージは3種類](https://qiita.com/RPAbot/items/95e8e76199196f23664d)存在します。その中で、ローカルPCのファイルを操作できるパッケージは**「Excelの基本操作」**および**「Excelの高度な操作」**です。前者はExcelがインストールされていなくてもファイルを直接読み書きするパッケージ、後者はExcelを使って操作するためのパッケージです。通常はExcelがインストールされているので後者を使うのがお勧めです。ちなみに、前者と後者で同じ名前のアクションがいくつかありますが、動作が違うものがあるので注意が必要です。この記事では一番ハマりそうな「セルを取得」関係のアクションでセルの値を読んだ時の値の違いについて解説します。

**環境**

* Automation Anywhere Enterprise A2019.13 (ビルド4705)
<font color="Red">(後述の通り、2020年9月中旬に登場したA2019.16 (ビルド6439) 以降は、Excelの高度な操作で新しいオプションが登場して、動作を選べるようになりました)</font>


**参考記事**

* [【Automation Anywhere A2019】 3種類のExcelパッケージの違い+Data Table](https://qiita.com/RPAbot/items/95e8e76199196f23664d)
* [Automation Anywhere A2019でExcel操作をする](https://qiita.com/RPAbot/items/fe30755c674eae801656)
* [Automation Anywhere A2019 変数型「日時 (Datetime)」に関するTips](https://qiita.com/RPAbot/items/04d82c204450c71995d6)

# 現象: Excel上で表示されている内容と違う値が取得される...
以下のようなExcelファイルを用意します。

**A1**: 数値で3.141592 (表示上は "3")
**A2**: 日付で2020/5/1
**A3**: 通貨で100.05 (表示上は "$100")

これはよくあるタイプのファイルですね。値として何が入っているかはセルをダブルクリックするか、アクティブなセルにして数式バーを見ると、書式なしの値が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/b4d07ed5-d81d-15a2-eb8c-831b195e4ecb.png)

このファイルに対して、以下のような2種類のBotで読み込みと表示を行います。それぞれ「Excelの基本操作」「Excelの高度な操作」を使ってExcelファイルを開き、特定のセル (A1) を読み込み文字列変数に保存、それをメッセージボックスで表示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/f1854bbf-cc41-b48b-74d6-6b10a6f78497.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/5c1113a7-d584-51b6-6334-7256dfcbdd48.png)

### A1 (数値で3.141592 (表示上は "3"))を読み込ませた結果
「Excelの基本操作」では値そのもの、「Excelの高度な操作」では書式設定を通して表示されている文字列が取得されていることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/6606be75-7b8d-d61c-6dac-2b5f6afa4728.png)

### A2 (日付で2020/5/1)を読み込ませた結果
「Excelの基本操作」では整数が返ってきています。これは**「シリアル値」**と呼ばれるもので、Excelでも日付は内部では整数として格納されており、書式設定を通して日付形式で表示されます。日付のシリアル値については数式バーやセルのダブルクリックでも表示されません。(書式を数値に変更すると表示されます。)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/cb83295a-bcfb-6d7c-bc31-3af1eb9432f2.png)

※ Excelのシリアル値を日時型変数に正しく格納するためにはBot Storeで配布されている**「日時 (日本)」**パッケージを使います。詳しい使い方は[こちらの記事](https://qiita.com/RPAbot/items/04d82c204450c71995d6)を参照してください。

### A3 (通貨で100.05 (表示上は "$100"))を読み込ませた結果
これもA1と同様、「Excelの基本操作」では値そのもの、「Excelの高度な操作」では書式設定を通して表示されている文字列が取得されていることがわかります。値としては通貨記号も持っていないことになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/540cf365-1c1d-7d40-d05a-32275c056323.png)

# A2019.16 (ビルド6439)以降の動作
「Excelの高度な操作」では、新しいオプションが追加され、セルに表示されている書式の文字列をそのまま取り出す (元々の高度な操作の動き) のか、セルに保持されている内部の値を抜き出す (基本操作の動き)のかを選べるようになりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/ec37bc40-929e-b9f5-ba67-0a2bee73a9a3.png)



# まとめ
このように、「Excelの基本操作」と「Excelの高度な操作」では、同じ「セルを取得」アクションを使っても得られる値が異なることがわかりました。これはUiPathでも同様にハマりポイントの1つになっているため、注意しましょう。
x86 SSE,  AARCH64 NEON での sqrt のメモ

# 前提

単精度とする

# C math

https://cpprefjp.github.io/reference/cmath/sqrt.html

`sqrt(0.0) = 0.0`, `sqrt(-0.0) = -0.0`, `sqrt(-1.0) = -nan`

# `_mm_sqrt_ps`

SSE2 命令の sqrt も, C math と同様になる. つまり `+/-0.0` の入力の場合は `+/-0.0`, 負数の場合は `-nan` となる.

# AARCH64 NEON

AARCH64 NEON(AARCH32 も?)には sqrt 命令がある(近似を求める sqrte も)

```
#include <cstdint>
#include <cstdio>
#include <cmath>

#include <arm_neon.h>

struct FP32
{
  union {
    float f;
    uint32_t ui;
  };
};

int main(int argc, char **argv)
{
  float32x4_t a = vdupq_n_f32(-1.0f);

  float32x4_t c = vsqrtq_f32(a);

  __attribute__((aligned(16))) float buf[4];

  vst1q_f32(buf, c);

  FP32 fp;
  fp.f = buf[0];

  printf("ret = %g(0x%08x)\n", buf[0], fp.ui);

  return 0;
}
```

```
sqrt(+0.0) = +0.0
sqrt(-0.0) = -0.0
sqrt(-1.0) = nan(0x7fc00000)
sqrt(+inf) = +inf
sqrt(-inf) = nan(0x7fc00000)
```

SSE とは異なり, nan の場合に符号がつかない.
MariaDBをDocker上で起動する

基本的なことだけど、忘れそうなので・・・・備忘録を含めてアウトプットを行います。


今回使う環境は・・・・

|言語やフレームワーク      |version        |
|:--------------------|--------------:|:------------------:|
|spring Boot          |  2.3.1.RELEASE|
|sequel pro| DBをGUI操作ができるツール |



ではでは、早速・・・・・

# Dockerを使って、MariaDBを起動

![スクリーンショット 2020-07-23 14.48.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270887/60a3ad5a-2ad8-a753-6ee7-e02cccfe2f6f.png)

このように、Dockerディレクトリを作成して、「docker-compose.yml」とymlファイルを作成する



```docker:docker-compose.yml
version: "3"
services:
  db:
    image: mariadb
    restart: always
    ports:
      - 3307:3307（ホストのポート番号：コンテナ内のポート）
    command: --port 3307
    environment:
      - MYSQL_ROOT_PASSWORD=ユーザー名がrootだったときのパスワード
      - MYSQL_DATABASE=sample（データベース名を作成する）
      - MYSQL_USER=user1(root以外のユーザー名を作成する）
      - MYSQL_PASSWORD=password(root以外のユーザー名のパスワードを作成する）


  adminer:
    image: adminer
    restart: always
    ports:
    - 8000:8000

```

ホストとは？

- ローカルPC（Mac, Windwosなど）などの自分の」環境を指している
- 今回は、ホストのポート番号とコンテナ内にあるMariaDBのポートを指定している感じ


```
command: --port 3307
```

- デフォルトでのポート番号は、`3306`を指しているため、複数のサービスを立ち上げた場合には、**使われているから起動できない**などのエラーが表示されてしまう。これを防ぐために、portを指定している。


# Sequel Proで接続できるのか確認

<img width="562" alt="スクリーンショット 2020-07-23 15.47.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270887/11455861-84fb-c2f5-8093-688ba24993f6.png">

ホスト: 127.0.0.1 or localhostになる
ユーザ名: root or MYSQL_USERで指定した名前
パスワード： MYSQL_ROOT_PASSWORD or MYSQL_PASSWORDで指定したパスワード
データベース： MYSQL_DATABASEで指定したDB名
ポート： `ports:`に書かれているポート番号

接続とい青いボタンを押して、Excelのような表が出れば、接続成功です。


## 引用サイト
- https://note.com/sunakujira/n/n8e85ad918888
- https://qiita.com/koinori/items/7ad2c8b560b27c6a50a9


**以上！！!**