OmniAICreator/Qiita-1.07M huggingface dataset:
点字メーカープログラム

## プルリクエストのリンク

https://github.com/JunichiIto/tenji-maker-challenge/pull/5

## ロジックの解説

- まず、ローマ字を0〜63のコード列に変換し、コード列を整形して出力する方針としました。この(codesの)整形は次で行なえます(左上の点を最上位ビットとする)。

```rb
codes.map{|e|('%06b'%e).tr('01','-o').scan(/../)}.transpose.map{|e|e*' '}*"\n"
```

- さてコード列ですが、訓令式ということは(ヂとヅとヲは厳密には訓令式と異なる形となるが)母音と子音を分離できるということです。そこでまず母音と子音の辞書を作成しました。複数の(点字)文字を使う子音もあるので、子音の辞書の値は配列としました。そのうえで、子音の最後の要素の値と母音の値についてビット和を取ったものを(その音素の)コード列としました。子音がYおよびWの場合は別の母音の辞書を使うようにしました。母音を一番下まで下ろす際に、母音によってシフト数が異なるためです。

- 撥音に関して、実用性の観点から'SI NN I'と'SI N I'を区別したかったので、スペースは無視して連続で拾えるようにしました[^1]。
- その上で、全体の流れはおおまかに以下のとおりとなります。
    - 子音が出現したら例外を除きバッファに溜めておく
    - 母音が出現したらバッファを子音としてコード列に変換
    - 同じ子音が連続して出現したら、
        - Nであれば「ん」を出力してバッファを空に
        - バッファの子音が2文字(以上)であったら(KYなど)エラー
        - それ以外であれば「っ」を出力(バッファはそのまま)
            - (撥音の事情があったため、せっかくなら促音にも対応しようということとなりました。)
    - 変換終了時、バッファに子音が残っていれば、Nであれば「ん」を出力、それ以外ならエラー

## コードのアピールポイント

- を、促音、長音、濁音、半濁音、拗音・拗半濁音に対応しています。
    - ヂ、ヅ、ヲはdi/du/woで、これだけは訓令式でないのでご注意下さい
    - ただし「こうもり」を 「こーもり」に変換するようなことは自動でやってくれないので正しく入力する必要があります
    - (あとは助詞の「へ」と「は」とか)
    - また、ツァ行(TS)、ファ行(F)やヴァ行(V)にも対応していますが、訓令式ベースなのであくまでおまけということでお願いいたします。
        - ヘボン式でないので、TSUと入れるとツゥのように変換されてしまいます。
        - TH行とかTW行とかはほとんど例外の扱いなので対応していません。
            - そこまで例外が伴うなら全音素を辞書にするアプローチを取るべきですが、必須要件ではない上にプログラムがシンプルでなくなるということもあります。
- 半角スペースは入っていてもいなくても構いません(というかこうしないと促音に対応できない)。
- 文字列かどうかのチェックはしていませんが、「each_charに反応しブロックの引数が1文字のStringである」オブジェクトを作ることはまずありませんが不可能ではないので、あえて余地を残しています。
- スタンドアローンスクリプトとしても実行可能としています。
- Braille Patterns Unicodeを出力する機能があります。

## 伊藤さんにメッセージ

CodeIQではありがとうございました。今回もよろしくお願いいたします。

## 感想

- 実は点字の仕組み自体はポケモンルビー・サファイアのレジイベント攻略時に把握していました。 **もう18年も前なのね。**
- さらにローマ字からカタカナに変換する関数を他のCodeIQの問題で作成済みだったので、テストコード通過には実は30分もかかっていません…。

### 懺悔

- Advent Calendarが終わったから言えることですが、数値を2進数リテラルで書いたほうがいいと思ったのは(当然こちらで答案を作ったあとですが)他の方の答案を拝見してのことでした。
- VowelsDownは「最下段まで下ろした母音ですが」、なぜ最下段まで下ろすのかのコメントは書くべきだったと思いました。
- codes_to_tenjiの説明があっさりしすぎているのはそのとおりで、これは2日目の記事を見て気づきましたが後の祭りでした。
- スペースのハンドラを空欄にしたのは故意でした。すみません。理由としてはスペースを出力するようにすると仕様を外れてしまうためというのがありました。

[^1]: 撥音に対応するのが要件でなければ促音のことも考えなくてよいはずなので、シンプルなプログラムになったとは思います…。
WSL2でDockerを使用する際の権限問題を解決するシンプルな方法（docker-compose.yml使用）

# 免責
この記事の解決方法は対処療法的なものであり、本来はもっと適切なやり方がある、いわゆる「正しくない」方法である可能性があります。申し訳ございません、ご了承下さい。

## 私が直面した問題
最初はマウントしたディレクトリ内のファイルをWSL2側から編集できないという問題がありました。この問題には Visual Studio Code Remote - Containers を使用することで対処しました。

しかし、Reactの勉強を始めたときに、マウントしたディレクトリ上でコンテナ側から `npx create-react-app my-app` を実行しても権限問題によりエラーが出力されてしまいました。これは VS Code の Remote Containers 拡張機能を使用しても解決できませんでした。

# 原因

この問題の原因を以下に示します。

- コンテナ側のデフォルトユーザはrootユーザ（uid=0）、コンテナ側で作成するファイル、ディレクトリの所有者もrootユーザ
- WSL2側のデフォルトユーザはWSL2ユーザ（uid=1000）、マウントしているディレクトリの所有者はWSL2のユーザ

これらから**現在のユーザとファイルもしくはディレクトリの所有者が異なる**という状況が発生し、権限問題が発生しているようです。

![hoge2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442538/c1ec43e9-61f9-15f7-b9be-18bd7f450472.png)

つまり、この問題を解決するには、ディレクトリやファイルの権限を変更するか、コンテナ側のユーザとWSL2のユーザを合わせる必要があります。

# 解決方法１
ディレクトリやファイルの権限を変更する方法です。

権限が問題となっている側（Permission deniedが発生する側）で以下のファイル及びディレクトリの所有者を変更するコマンドを実行します。

ホスト側で弾かれる場合はホスト側で問題となっているファイル及びディレクトリの所有者を変更します。

```
sudo chown -R $USER:$USER .
```

コンテナ側で弾かれる場合はコンテナ側で問題となっているファイル及びディレクトリの所有者を変更します。

```
chown -R root:root .
```

Docker公式ドキュメントの [Railsアプリのセットアップ](https://docs.docker.com/samples/rails/) ではこの方法が使用されています。


# 解決方法２
docker-compose.yml を使用し、コンテナ側のユーザをWSL2のユーザに合わせる方法です。

まず `docker-compose.yml`ファイルに次の記述をします。

```
user: "${UID_GID}"
```

例えば次のように記述します。

```docker-compose.yml
# これは例です。
version: '3'
services:
  app:
    build: .
    tty: true
    ports:
      - 3000:3000
    volumes:
      - ./src:/app
    user: "${UID_GID}"
```

そして docker-compose up する際に、次のようにして uid と gid を環境変数として渡します。

```
UID_GID="$(id -u):$(id -g)" docker-compose up
```

これによりコンテナ内のユーザとWSL側のユーザを一致させることができます。
試しにホスト側とコンテナ側で`id`コマンドを叩き、表示される uid 及び gid が一致しているか確認してみてください。一致していれば成功です。

# 余談
次のコマンドをエイリアス登録しておくのがおすすめです。

```'.bashrc'
alias ug='UID_GID="$(id -u):$(id -g)"'
```

このようにすると、 `ug docker-compose up` のように `ug` を頭につけるだけで docker-compose のコマンドがそのまま使えます。

# 参考


https://futureys.tokyo/how-permission-should-be-set-for-developing-inside-a-container-using-wsl-2/

原因特定の参考にさせていただきました。  

----

https://stackoverflow.com/questions/56844746/how-to-set-uid-and-gid-in-docker-compose

解決方法はここから拝借いたしました。
【SPARQL】レコード単位で保持されるデータを列の形式で取得したい

## 概要
以前に[【SPARQL】独自の型の値をFilterで絞り込みしたい](https://qiita.com/someone7140/items/d42ed1e97307951df52a)の記事で、SPARQLにおける型の話を取り上げました。
今回はデータの取得形式について少し書いてみたいと思います。

## やりたいこと
今回も法人情報のデータを取得できるAPI、[gBizINFO](https://info.gbiz.go.jp/)の財務データを例にします。
以下のように財務データを取得するクエリを発行した場合、

```sparql
PREFIX hj: <http://hojin-info.go.jp/ns/domain/biz/1#>
PREFIX ic: <http://imi.go.jp/ns/core/rdf#>
SELECT ?cID ?name ?sihyou ?value
FROM <http://hojin-info.go.jp/graph/zaimu>
WHERE {
  ?s hj:法人活動情報 ?o .
  ?o ic:名称/ic:表記 ?name .
  ?o ic:ID/ic:識別値 ?cID .
  ?o hj:数量コレクション/hj:数量 ?c .
  ?c hj:指標 ?sihyou .
  ?c ic:数値 ?value .
  FILTER(?cID= "1180301018771")
}
limit 100
```

以下のように、1つの勘定につき1レコードのような形式で取得されます。

```json
{
   "cID": {
     "type": "literal",
     "value": "1180301018771"
    },
   "name": {
     "type": "literal",
     "value": "トヨタ自動車株式会社"
   },
   "sihyou": {
     "datatype": "http://imi.go.jp/ns/core/rdf#コード型",
     "type": "literal",
     "value": "http://hojin-info.go.jp/code/財務情報/純資産額"
   },
   "value": {
    "datatype": "http://www.w3.org/2001/XMLSchema#decimal",
    "type": "literal",
    "value": "12590891000000"
   }
},
{
   "cID": {
     "type": "literal",
     "value": "1180301018771"
    },
   "name": {
     "type": "literal",
     "value": "トヨタ自動車株式会社"
   },
   "sihyou": {
     "datatype": "http://imi.go.jp/ns/core/rdf#コード型",
     "type": "literal",
     "value": "http://hojin-info.go.jp/code/財務情報/売上高"
   },
   "value": {
    "datatype": "http://www.w3.org/2001/XMLSchema#decimal",
    "type": "literal",
    "value": "12201444000000"
   }
}
```

これを1レコード1勘定ではなく、1レコードに複数の勘定をまとめて取得するということを実現したいです。

## 対応
こちらの[6.3 複数のオプションのグラフ・パターン](http://www.asahi-net.or.jp/~ax2s-kmtn/internet/rdf/rdf-sparql-query.html#MultipleOptionals)の記載にある通り、`OPTIONAL`句を使うことで実現できそうです。
`OPTIONAL`はSQLで言うところの、外部結合のような役割を果たす機能です。今回の財務データの例でいくと、イメージ的には会社情報に対し、純資産額と売上高を左外部結合するような処理になります。

## クエリサンプル
上記の財務データの例に示した内容で、純資産額と売上高を列形式で取得するクエリです。

```sparql
PREFIX hj: <http://hojin-info.go.jp/ns/domain/biz/1#>
PREFIX ic: <http://imi.go.jp/ns/core/rdf#>
SELECT ?cID ?name ?netAssetName ?netAssetValue ?salesName ?salesValue
FROM <http://hojin-info.go.jp/graph/zaimu>
WHERE {
  ?s hj:法人活動情報 ?o .
  ?o ic:名称/ic:表記 ?name .
  ?o ic:ID/ic:識別値 ?cID .
  OPTIONAL{
    ?o hj:数量コレクション/hj:数量 ?c .
    ?c ic:数値 ?netAssetValue .
    ?c hj:指標 ?netAssetName .
    FILTER(?netAssetName = "http://hojin-info.go.jp/code/財務情報/純資産額"^^ic:コード型)
  } .
  OPTIONAL{
    ?o hj:数量コレクション/hj:数量 ?c2 .
    ?c2 ic:数値 ?salesValue .
    ?c2 hj:指標 ?salesName
    FILTER(?salesName = "http://hojin-info.go.jp/code/財務情報/売上高"^^ic:コード型)
  } .
  FILTER(?cID= "1180301018771")
}
limit 100
```
apacheのエラーログがstderrには出せずstdoutには出せた話

# 現象

Dockerで動かしているapache(※)のエラーログをDocker Logsに出したかったので、以下のように標準エラー出力するように設定したがDocker Logsに出力されない。

```
ErrorLog /dev/stderr
```

一方、標準出力を指定するとDocker Logsに出力される。

```
ErrorLog /dev/stdout
```

※httpdイメージは使っておらず、CentOSイメージの中でインストールしたapache

# 調査結果

httpdプロセスの `fd/2` がttyではなくログファイルを向いていた。

```
# ls -l /proc/1/fd
total 0
lrwx------ 1 root root 64 Nov  3 14:53 0 -> /dev/pts/0
lrwx------ 1 root root 64 Nov  3 14:53 1 -> /dev/pts/0
l-wx------ 1 root root 64 Nov  3 14:53 2 -> /var/log/httpd/error_log
以下省略
```

# 補足情報

PHPのエラーは以下の設定でDocker Logsに出力できた。

```
ini_set('error_log', 'php://stderr');
```

CGI版のphpであればphp.iniの設定で出せるかもしれない？

```
display_errors = stderr
```
mysqlでのJsonの使い方

メモです。

## mysql でJsonを使ってみる
### 定義
こんな感じ

```sql
CREATE TABLE `test_ｔable` (
	`id` CHAR(50) NOT NULL,
	`create_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
	`data` JSON NOT NULL,　 <---- Json
	);
```
### データ追加

```sql
INSERT INTO test_ｔable (id,data) 
        VALUES ('test','{"a":"hogehoge"}')
```
### 参照
基本

```sql
select * from test_ｔable;
```

json が見たい
これが使える

```sql
json_extract( Jsonのカラム ,'$.Json_key')
```

```sql
select json_extract(data,'$.a') from test_ｔable;
```

## ちょっと、どうでもいい話
### Heidisql なんかでのJsonの消し方
上記のソフトでレコードを消す際、Jsonが含まれていると、消せないことがあった。
送信されている、sql を見ると消したレコードデータでJsonの中身が''で送信されていた
こんな感じ

```
'{"a":"test"}'
```
一見間違ってないように見えるけど、冷静に考えるとJsonではなく文字列として送っている？
が原因で消せなかった。（そこまで、細かく検証してないです）

### Jsonデータでkeyを数字にした時
数字をキーにして保存した時、Viewを自動的に作成されなかった。
Json形式を利用して色々なViewを作成されるようにしたが、数字を考えてなかった話

結論　ｓｑｌの構文エラー
Jsonで数字のキーを扱うときは、一手間いるらしい

```sql
json_extract(json_data,'$."1"')
```
Entityクラスの＠Idアノテーションでハマった話

Springbootでアプリケーションを作る際に、Entityクラスの主キーに＠Idをつける場合があります。
本日はこの＠Idアノテーションでハマった話を書いていこうと思います。

#@Idアノテーション
@idアノテーションは、以下のように説明されています。
>javax.persistence.Id
Specifies the primary key of an entity. The field or property to which the Id annotation is applied should be one of the following types: any Java primitive type; any primitive wrapper type; String; java.util.Date; java.sql.Date; java.math.BigDecimal; java.math.BigInteger.
>The mapped column for the primary key of the entity is assumed to be the primary key of the primary table. If no Column annotation is specified, the primary key column name is assumed to be the name of the primary key property or field.

エンティティの主キーを指定します。そのフィールドとプロパティは次の型を使うべきです。
Javaのプリミティブ型、プリミティブラッパータイプ、String、Date、math、bigDecimal,BigInteger
エンティティの主キーのマップされた列は、主テーブルの主キーであると見なされます。 列の注釈が指定されていない場合、主キーの列名は主キーのプロパティまたはフィールドの名前であると見なされます。

つまり主キーであると明示するアノテーションであるということはわかります。

```java:Emtity.java
@Id
@Column(name = "user_id")
private int userId;
```

user_idのカラムに対応付いており、userIdのフィールドは主キーであることを示しています。
ここで問題が起きました。

RestAPIでsaveを行った際に、主キーとなるデータをnullの状態でsendするのですが、nullではなく、0がRequestされてしまいます。
![スクリーンショット 2021-11-05 0.24.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296562/b30c0a08-2f01-b060-48d1-ba14e3386347.png)

これだと最初の0の状態の1回のみはsaveが成功しますが、その後のsaveが転けてしまいます。
これの問題解決方法は、Long型にすることです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296562/689c64cf-d6f7-b32e-5bfe-ca1f284fb2b8.png)
Exampleにint型を使用していたので使ってみたら無事nullをRequestすることに成功しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296562/05048d9c-2195-73a0-5870-9bd2268b86a0.png)

ただしこれだけでは足りません。Postgresqlを使っていますが、シーケンスを貼ることができないのでどちらにしろ実行は失敗してしまいます。
そこで次を追記します。
`@GeneratedValue(strategy = GenerationType.IDENTIFY)`


```java:Emtity.java
@Id
@Column(name = "user_id")
@GeneratedValue(strategy = GenerationType.IDENTIFY)
private int userId;
```

これを追加すると、identify列を使用して，主キー（primaryキー）を生成してくれるので、
番号が重複してエラーになることもありません。identify列に関しては次の記事を参照
https://www.magicsoftware.co.jp/files/magic_help/Magicxpa2/Data_Management/SQL_Considerations/Identity_Column.htm

シーケンスについてはまだまだ勉強が必要そうですね。
【備忘録】previewProviderを使用し、プレビュー画面でレイアウトを確認する。

#previewProviderとは？

Xcode上でプレビュー画面を表示する際に使用する。
メソッド内に記述した内容はプレビュー画面にしか表示されない。

例）

```
struct CircleCheck_Previews: PreviewProvider {
    static var previews: some View {
        VStack {
            Image(systemName: "hoge")
        }
    }
}
```


#レイアウト（配置）
```
struct CircleCheck_Previews: PreviewProvider {
    static var previews: some View {
        VStack {
            CircleImage()
        }
    }
}
```

縦並びにする（VStack）

```
　　VStack {
        CircleImage()
        　}
```


横を並びにする（HStack）

```
　　HStack {
        CircleImage()
        　}
```

前後を並びにする（ZStack）

```
　　ZStack {
        CircleImage()
        　}
```

画面を分ける（Group）

```
　　Group {
        CircleImage()
        　}
```

参考：https://developer.apple.com/documentation/swiftui/previewprovider
【AWS/EC2/Amazon Linux2】curl: (60) SSL certificate problem: certificate has expired

## 背景

AWS EC2(Amazon Linux2)上で、最新のGoogle Chromeをダウンロードしようと
下記Curlコマンドを実行しました。

```terminal
sudo curl https://intoli.com/install-google-chrome.sh | bash
```

すると、タイトルにも記載したエラーが出ました。

```terminal
curl: (60) SSL certificate problem: certificate has expired
More details here: https://curl.haxx.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
```

## 原因

私の場合、Let's Encrypt クロス署名 DST ルート CA X3 の期限切れが原因でした。

## 解決策

AWSの公式ドキュメント見てたら、解決策ありました。
さすが、AWS公式。

https://aws.amazon.com/jp/premiumsupport/knowledge-center/ec2-expired-certificate/

下記コマンドを入力して手動修復をすれば、無事Curlコマンドが通るようになりました。
ご自身のEC2のOSに応じて、使用してみてください。

```
sudo yum update ca-certificates
```

### リポジトリの GUID がロックされた AMI が使用している場合

Elastic Beanstalk など、リポジトリの GUID がロックされた AMI が使用されている場合は、次のコマンドを使用して、更新された CA 証明書パッケージをインストールできます。

### Amazon Linux1
```terminal
sudo yum install https://cdn.amazonlinux.com/patch/ca-certificates-update-2021-09-30/ca-certificates-2018.2.22-65.1.24.amzn1.noarch.rpm
```

### Amazon Linux2

```terminal
sudo yum install https://cdn.amazonlinux.com/patch/ca-certificates-update-2021-09-30/ca-certificates-2021.2.50-72.amzn2.0.1.noarch.rpm
```

同じエラーで困っている方の助けになれば幸いです。
やはり、困った時にまず頼るべきは公式ですね。
eksctlコマンドでEKSのクラスターを作成する

eksctlコマンドを使ってEKSのクラスターを作成した際のメモ。
クラスター作成時に自動生成されたAWSリソースについてもまとめる。

## 準備
#### 前提

* awscliがインストール&設定済みであること
* AWSのリージョンは`ap-northeast-1`
* kubectlがインストール済みであること
* 実行環境
    * macOS Big Sur バージョン11.5.1


#### eksctlのインストール
インストール

    brew install eksctl

バージョンが`0.67.0`以上であることを確認

    eksctl version

## クラスターの作成
[公式ドキュメント](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/create-cluster.html)に習い、以下のコマンドを実行

    eksctl create cluster --name <name> --version 1.21 --with-oidc --without-nodegroup

↑のコマンドひとつでクラスターが立ち上がる。
（`--without-nodegroup`オプションをつけているのでノードは作成されない）

## 作成されたクラスターの設定情報

* ノードグループ
    * なし（作成しないオプションを設定したため）
* VPC
    * 自動生成されたVPC
* サービスIPv4範囲
    * `10.100.0.0/16`
* サブネット
    * 自動生成されたサブネット
        * パブリックサブネット * 3
        * プライベートサブネット * 3
* セキュリティグループ
    * クラスターセキュリティグループ
        * `eks-cluster-sg-<クラスター名>-xxxxxxxx`
        * クラスターセキュリティグループは、Kubernetes コントロールプレーンとクラスター上のコンピューティングリソース間の通信を制御するために使用される統合セキュリティグループです。（公式より）
    * 追加のセキュリティグループ
        * `eksctl-<クラスター名>-cluster-ControlPlaneSecurityGroup-xxxxxxxx`
        * 追加のクラスターセキュリティグループは、Kubernetes コントロールプレーンからの通信を制御して、アカウントのリソースを計算します。（公式より）
* APIサーバーエンドポイント
    * パブリック
* パブリックアクセスソースの許可リスト
    * 0.0.0.0/0
* アドオン
    * なし
* ログ記録
    * なし

#### その他
eksctlを実行したローカル環境のkubeconfigも自動で設定される。
kubeconfigが設定されなかった（できなかった）場合は以下のコマンドで設定する。

    aws eks --region [region] update-kubeconfig --name [cluster_name] --profile [profile]

## クラスター作成時に自動生成されたもの
※上記コマンドオプションでクラスターを作成した場合

#### VPC
* CIDR: `192.168.0.0/16`
* DNSホスト名：有効

#### サブネット
* パブリックサブネット * 3
    * 3AZ
    * パブリックIPv4自動割当：はい
* プライベートサブネット * 3
    * 3AZ 
    * パブリックIPv4自動割当：いいえ

#### インターネットゲートウェイ
* パブリックサブネットのルートテーブルに紐付け

#### NATゲートウェイ
* プライベートサブネットのルートテーブルに紐付け

#### Elastic IP
* NATゲートウェイに紐付け

#### セキュリティグループ
* `default`
    * インバウンド
        * 自セキュリティグループ
    * アウトバウンド
        * 0.0.0.0/0
* `eks-cluster-sg-<クラスター名>-xxxxxxxx`
    * EKS created security group applied to ENI that is attached to EKS Control Plane master nodes, as well as any managed workloads.
    * インバウンド
        * 自セキュリティグループ
        * eksctl-<クラスター名>-cluster-ClusterSharedNodeSecurityGroup-xxxxxxxx
    * アウトバウンド
        * 0.0.0.0/0
* `eksctl-<クラスター名>-cluster-ClusterSharedNodeSecurityGroup-xxxxxxxx`
    * Communication between all nodes in the cluster
    * インバウンド
        * 自セキュリティグループ
        * eks-cluster-sg-<クラスター名>-xxxxxxxx
    * アウトバウンド
        * 0.0.0.0/0
* `eksctl-<クラスター名>-cluster-ControlPlaneSecurityGroup-xxxxxxxx`
    * Communication between the control plane and worker nodegroups
    * インバウンド
        * なし
    * アウトバウンド
        * 0.0.0.0/0

#### IAM Role
* `AWSServiceRoleForAmazonEKS` (未作成の場合)
    * AmazonEKSServiceRolePolicy
* `eksctl-<クラスター名>-cluster-ServiceRole-xxxxxxxx`
    * AmazonEKSClusterPolicy
    * AmazonEKSVPCResourceController
    * eksctl-eks-test-cluster-PolicyCloudWatchMetrics（インラインポリシー）
    * eksctl-eks-test-cluster-PolicyELBPermissions（インラインポリシー）
* `eksctl-<クラスター名>-addon-iamserviceaccount-kube-Role1-xxxxxxxx`
    * AmazonEKS_CNI_Policy
    * 信頼されたエンティティにoidcの設定あり


## クラスターの削除
以下のコマンドを実行

    eksctl delete cluster --name <name>

クラスター作成時に自動生成された関連リソースもすべて削除される。
railsチュートリアル第１１章 アカウント有効化のメール送信

##アカウント有効化のメール送信
アカウント有効化メールの送信に必要なコードを追加
このメソッドではAction Mailerライブラリを使ってUserのメイラーを追加
　Usersコントローラのcreateアクションで有効化リンクをメール送信するために使います。
このテンプレートの中に有効化トークンとメールアドレスのリンクを含め、使っていきます。

###送信メールのテンプレート

####メイラーの生成
```
ubuntu:~/environment/sample_app (account-activation) $ rails generate mailer UserMailer account_activation password_reset
Running via Spring preloader in process 11611
      create  app/mailers/user_mailer.rb
      invoke  erb
      create    app/views/user_mailer
      create    app/views/user_mailer/account_activation.text.erb
      create    app/views/user_mailer/account_activation.html.erb
      create    app/views/user_mailer/password_reset.text.erb
      create    app/views/user_mailer/password_reset.html.erb
      invoke  test_unit
      create    test/mailers/user_mailer_test.rb
      create    test/mailers/previews/user_mailer_preview.rb
```

account_activationメソッド、password_resetメソッドが生成されました

####アカウント有効化メイラーのテキストビュー
app/views/user_mailer/account_activation.text.erb

```text
User#account_activation

<%= @greeting %>, find me in app/views/user_mailer/account_activation.text.erb
```

####アカウント有効化メイラーのHTMLビュー
app/views/user_mailer/account_activation.html.erb

```html
<h1>User#account_activation</h1>

<p>
  <%= @greeting %>, find me in app/views/user_mailer/account_activation.html.erb
</p>
```

####Applicationメイラー
app/mailers/application_mailer.rb

```rb
class ApplicationMailer < ActionMailer::Base
  default from: "noreply@example.com"
  layout 'mailer'
end
```
####生成されたUserメイラー
app/mailers/user_mailer.rb

```rb
class UserMailer < ApplicationMailer

  def account_activation(user)
    @user = user
    mail to: user.email, subject: "Account activation"
    # mailにsubjectキーを引数として渡しています。
    # この値は、メールの件名にあたります
  end

  def password_reset
    @greeting = "Hi"

    mail to: "to@example.org"
  end
end
```
####アカウント有効化のテキストビュー
app/views/user_mailer/account_activation.text.erb

```
Hi <%= @user.name %>,

Welcome to the Sample App! Click on the link below to activate your account:

<%= edit_account_activation_url(@user.activation_token, email: @user.email) %>
```

####アカウント有効化のHTMLビュー
app/views/user_mailer/account_activation.html.erb

```
<h1>Sample App</h1>

<p>Hi <%= @user.name %>,</p>

<p>
Welcome to the Sample App! Click on the link below to activate your account:
</p>

<%= link_to "Activate", edit_account_activation_url(@user.activation_token,
                                                    email: @user.email) %>
```

####演習
1.
コンソールを開き、CGIモジュールのescapeメソッド（リスト 11.15）でメールアドレスの文字列をエスケープできることを確認してみましょう。このメソッドで"Don't panic!"をエスケープすると、どんな結果になりますか?

```rb
>> CGI.escape('foo@example.com')
=> "foo%40example.com"
>> CGI.escape("Don'tpanic!")
=> "Don%27tpanic%21"
```
Markdownを使ってみたかったので

# 目的

<font color="Red">**Markdownで練習がてら色々書いてみる。**</font>

# できること

* リスト表示( * )もかける


- [ ] ToDoも
- [x] 書けたりする

> 引用もできる

```python
print('コードもかけるよ！')
```

`rgb(255,0,0)` 色が変わるかと思ったけどそんなことなかった？？
Qiitaはいけるっぽい。Typoraは駄目だった。

*強調（イタリック体）*できる。**太字にも。**

# 気になること

* 目次って書けないんですかね？？
* フォントの色はHTMLで変えるしかない？？

# Markdownでやりたいこと

* スライド資料を作ってみたい
* Notionでいろいろ活用できそう

# 参考ページ
* 困ったらここを読めばいいはず（まだあまり読んでいない）

https://qiita.com/Qiita/items/c686397e4a0f4f11683d
heroku laravel 画像が表示されない

この記事ではheroku上でのシンボリックリンク設定方法についてご紹介していきます。

##起きたこと
localでは正常に画像が表示されていたのですが、herokuにデプロイした途端、急にheroku上でのみ画像が表示されなくなってしまいました。

![スクリーンショット 2021-11-03 22.11.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601015/10d649e4-1973-4eb3-d1f1-e98e578dc4a7.png)

それも、エラーが一切出なく、登録機能も正常に動作するので原因が全く分からないのです。。
数日悩んだ末、色々検索していた際に「シンボリックリンクの設定」について書かれている記事に辿り着きました！
https://qiita.com/en_tokiya/items/5afab752c5826e4dcc62

local環境で動作させていた時にシンボリックリンクは設定していたのですが、どうやら本番環境にそのまま反映されるわけではないようで、デプロイ後に再設定が必要とのことでした。

シンボリックリンクを本番環境用に設定して無事画像の表示がされるようになったので、同じ事象で悩まれてる方は是非参考にしてみてください！

##シンボリックリンク設定
設定は簡単です！
先ほど紹介させてもらった記事にも設定手順が記載されていますが、改めてこちらの記事でも説明しておきたいと思います。
※なお、設定前に確認しておく事項があるのでそちらについてはご紹介した記事をご覧ください。
https://qiita.com/en_tokiya/items/5afab752c5826e4dcc62

設定は下記の手順でコマンドを実行していきます！

```
// /app、/database、/routesなどが配置されてるアプリディレクトリで実行
$ heroku run bash //heroku上でコマンド操作できるようにする
```
これでheroku上のディレクトリでコマンド操作できるようになりました。
次に現在設定されているシンボリックリンクを削除します。

```
~ $ cd public // /publicに移動
~/public $ rm storage //現在のstorageファイルを削除
~/public $ ls -l //storageが削除されたことを確認
total 24
drwx------ 2 u31878 dyno 4096 Nov  4 03:09 css
-rw------- 1 u31878 dyno    0 Nov  4 03:09 favicon.ico
-rw------- 1 u31878 dyno 1735 Nov  4 03:09 index.php
drwx------ 2 u31878 dyno 4096 Nov  4 03:09 js
-rw------- 1 u31878 dyno   71 Nov  4 03:09 mix-manifest.json
-rw------- 1 u31878 dyno   24 Nov  4 03:09 robots.txt
-rw------- 1 u31878 dyno 1183 Nov  4 03:09 web.config
```

これで誤って設定されていたシンボリックリンクが削除されました。
次は正しいシンボリックリンクを設定していきます。

```
~/public $ cd　//アプリディレクトリに移動
~ $ php artisan storage:link //シンボリックリンク作成
The [/app/public/storage] link has been connected to [/app/storage/app/public].
The links have been created.
```

これでシンボリックリンクが新しく作成されましたね！
下記コマンドでstorageが再作成できたか確認します。

```
~ $ cd public // /publicに移動
~/public $ ls -l //storageが作成されたか確認
lrwxrwxrwx 1 u31878 dyno   23 Nov  4 13:51 storage -> /app/storage/app/public //作成されてますね！
~/public $ 
```

これでheroku上でのシンボリックリンクが無事作成されました！
次にローカルのディレクトリで設定していきます。

```
//ローカルのアプリディレクトリで実行
$ cd public
$ rm storage //現在のシンボリックリンクを削除
$ ln -s /app/storage/app/public storage
```

これで再設定できました！
設定コマンドは下記のような記述になっています。

```
$ ln -s リンク元 登録名
```
再度storageが作成されてることも確認できました！

```
% ls -l
lrwxr-xr-x ... storage -> /app/storage/app/public
```

では、最後に変更点をコミットしてherokuにデプロイしましょう！

```
$ git add storage
$ git commit -m 'コミットメッセージ'
$ git push heroku main
```

これで再度ブラウザで確認すると画像が表示されていることが分かるかと思います！！
初学者にとってエラーの出ない問題は辛いですよね。。
何がダメなのかが全く検討つかないので。
今回は無事解決できましたので、少しでも同じ事象で悩まれてる方の参考になれば嬉しいです！
Flutter、Firestoreで500件以上のbatch処理

## Flutter、Firestoreで500件以上のbatch処理

### 結果
```dart
Future deletePostsOfCurrentUser(User? currentUser) async {
    await FirebaseFirestore.instance
    .collection('posts')
    .where('uid',isEqualTo: currentUser!.uid)
    .get()
    .then((qshot) {
      WriteBatch batch = FirebaseFirestore.instance.batch();
      final docs = qshot.docs;
      int index = 0;
      docs.forEach((DocumentSnapshot doc) async {
        if ((index + 1) % 500 == 0) {
          // commit by 500 and initialize batch instance
          await batch.commit();
          batch = FirebaseFirestore.instance.batch();
        }
        batch.delete(doc.reference);
        index++;
      });
      // last commit
      return batch.commit();
    });
  }
```
C# 抽象とかインタフェスとか

学習の足しになればいいような結論だけ

C# **abstract**と**interface**の違い。

問題の根源は、多重継承によるメモリの無駄である。
あ、これは今度のネタにしよう。

abstractは単一の継承のみ許可する。
　フィールドを持てる。

interfaceは無制限の継承を許する。
　フィールドを持てない。
　抽象メソッドとプロパティはOK。（実装を持たないプロパティ宣言ということ。）

詳細はこちら

https://ufcpp.net/study/csharp/oop/oo_multipleinheritance/

こういう事を　教えるときに同時に教えた方がいい、教師役ってなんか頑張って欲しいわね。

間違ってたらごめんなさい。


~~困った事：
FindObjectOfType<>()メソッドにinterface型を指定して呼び出す事が出来ない。~~
ありがたい事にコメントを頂いてしまった。
一旦`<Object>`で取得してから、型チェックする流れで上手くいきました。
メタキーがEscなのは不便なのでOptionに変えたい

Macでnanoを使うにあたり、メタキー（M-）がどこなんだろうと探していたら、Escだった。
さすがに、Escは使いづらいので、別のキーに変えたい。

**Preferences**から**Profiles**→**Keys**で`Left Option key` or `Right Option key`を`Esc+`にすることで`Option`キーをメタキーとして使うことができるようになる。

![スクリーンショット 2021-11-04 23.45.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352836/0942a707-5b35-61c4-daba-a184a412ffd5.png)
auto_routeを使おうとしてビルドしたら、「 Error: The method 'AutoRouteInformationProvider.routerReportsNewRouteInformation' doesn't have the named parameter 'type' of overridden method 'RouteInformationProvider.routerReportsNewRouteInformation'.」というエラーがでたときの対処法

# はじめに
flutter webで動的にurlを生成し、さらにブラウザのバックボタンを有効にする方法としてauto_routeの勉強をしようとしていました。ところが、簡単なコードを書いてビルドしたところ

```
 Error: The method 'AutoRouteInformationProvider.routerReportsNewRouteInformation' doesn't have the named parameter 'type' of overridden method 'RouteInformationProvider.routerReportsNewRouteInformation'.
```
とエラーが表示されました。

#環境
MacOS BigSur
Flutter 2.5.3
Dart 2.14.4
auto_route: ^2.2.0
(auto_routeは3.04を一回試したのですが、以下のようなエラーがMessageにでたのであきらめて、うまくいっている人のVer2.20を採用しました）

```
Running "flutter pub get" in auto_route_sample...               
Because auto_route_sample depends on auto_route_generator ^3.0.4 which doesn't match any versions, version solving failed.
pub get failed (1; Because auto_route_sample depends on auto_route_generator ^3.0.4 which doesn't match any versions, version solving failed.)
Process finished with exit code 1
```


# 解決策
以下のサイトを参考にしました。
https://github.com/flutter/flutter/pull/88122

```
flutter --version
```
でチャンネルを確認するとmasterだったので、stableに変更したら解決するようです。（betaもうまくいきませんでした。このパッケージのバグなようです）

変更方法は

```
flutter channel stable
flutter upgrade
flutter pub get
```

です。

ちなみにこれをしても私は以下のようなエラーが出たので、
（エラーの文章なくしちゃったので、↓のURLから引っ張ってきました。verは違った気がしますが、内容は同じです）
https://github.com/dnfield/flutter_svg/issues/161


```
The current Dart SDK version is 2.1.2-dev.0.0.flutter-0a7dcf17eb. Because test_app depends on flutter_svg >=0.13.0 which requires SDK version >=2.2.0 <3.0.0, version solving failed. 
```

pubspec.yaml内のenvironment:sdk:を以下のように変更して、devを消しました。

```
environment:
  sdk: ">=2.12.0 <3.0.0"
```

これでもう一回pub getしてビルドしたところうまくいきました。

２時間ほど、このエラーで私はさまよったので誰かの参考になったら嬉しいです！
ファイルの先頭 N 行と末尾 M 行を取り出すワンライナー

## tee を使う方法

```bash
$ seq 100000 | nl -s: | tee -p >(head -n 10) >(tail -n 3) > /dev/null | sort -un | cut -d: -f2-
1
2
3
4
5
6
7
8
9
10
99998
99999
100000
```

### 処理の流れ

最初に `nl -s:` で行番号を付けます。次に `tee -p >(head -n 10) >(tail -n 3) > /dev/null` で先頭の 10 行と末尾の 3 行を取り出します。

取り出そうとする行数が入力テキストの行数より大きい場合は重複行が発生します。また、結果行の順序は保証されないため、`sort -nu` でソートし、重複行を削除します。

ここまでの処理で、以下の状態となります。

```bash
$ seq 100000 | nl -s: | tee -p >(head -n 10) >(tail -n 3) > /dev/null | sort -un
     1:1
     2:2
     3:3
     4:4
     5:5
     6:6
     7:7
     8:8
     9:9
    10:10
 99998:99998
 99999:99999
100000:100000
```

最後に `cut -d: -f2-` で行番号を削除することで、期待する結果を得ることができます。

### 上手くいかなかった方法

最初、以下のように書いたところ、期待する結果は得られず、しかも実行するたびに異なる出力が行われてしまいました。

冒頭に出したコマンドとの違いは、`tee` に `-p` オプションを指定しているかどうかだけです。これについて、コメント欄で @angel_p_57 さんに重要なポイントを教えていただきました。（次の項目へ）

```bash
$ seq 100000 | nl -s: | tee >(head -n 10) >(tail -n 3) > /dev/null | sort -un | cut -d: -f2-
1
2
3
4
5
6
7
8
9
10
5893
5894
5895
```

### プロセス置換と tee の -p オプション

`tee >(head -n 10) >(tail -n 3)` のように `>(COMMAND)` と書くと、bash のプロセス置換 (process substitution) になります。

プロセス置換は元のコマンドパイプラインとは非同期で実行されます。また、`tee` はパイプへの書き込みエラーが発生した場合、デフォルトでは直ちに終了します。`tee` の `-p` や `--output-error=MODE` オプションを指定することで、この動作を変更できます[^2]。

今回は `-p` (`--output-error=warn-nopipe` と同じ) を指定することで、発生した問題を解決できました。

[^2]: 次のコメントを参照: [#comment-38a252900c08a1132973](#comment-38a252900c08a1132973)

## pee を使う方法

```bash
$ seq 100000 | nl -s: | pee 'head -n 10' 'tail -n 3' | sort -nu | cut -d: -f2-
1
2
3
4
5
6
7
8
9
10
99998
99999
100000
```

[moreutils](https://joeyh.name/code/moreutils/) に含まれる pee を利用する方法です。コメント欄で @yoichi22 さんに教えていただきました[^2]。

`pee` は `tee` とは違い、標準入力の内容を標準出力に出力しません。パイプで使うことに特化した `tee` という感じのコマンドです。

[^2]: 次のコメントを参照: [#comment-a501a69601d8a4e269d1](#comment-a501a69601d8a4e269d1)

### 処理の流れ

基本的な考え方は `tee` を使う方法と同じです。

## 没案

試行錯誤して作ったものの、フィードバックを受けて、より良い方法が分かった今となっては微妙な方法です。

```bash
$ seq 100000 | nl -s: | tee >(sed '11,$d') >(tac | sed '4,$d' | tac) > /dev/null | sort -nu | cut -d: -f2-
1
2
3
4
5
6
7
8
9
10
99998
99999
100000
```

## 別解 1

入力データがファイルの場合は、次のように書くこともできます。

```bash
$ cat a.txt | head -n 10 && cat a.txt | tail -n 3
1
2
3
4
5
6
7
8
9
10
99998
99999
100000
```

## 別解 2

コメントで @angel_p_57 さんに教えていただいた sed で実現する方法です。[sedでのtailのシミュレート](https://qiita.com/angel_p_57/items/e7335f35ea5e1c7c3f02) でコードを分解して、一つ一つ解説されています。

```bash
seq 100000 | sed -n -e '1p;:L' -e '${p;q};h;n;2,10p;H;g;4,$D;bL'
```
[macOS][Cocoa]StoryboardでNSWindowControllerを使ったモーダルシートの表示

# StoryboardでNSWindowControllerを使ったモーダルシートの表示方式

調べるのにちょっと時間を要したので、自分への備忘録を兼ねて、実装方法をここにまとめておきます。

# ViewControllerの追加

モーダル表示させるViewControllerのソースファイル（例として`ModalSheetViewController`）を追加します。コードの内容は以下の通り。
（先に記載しましたが、後述のStoryboardに追加した後でも構いません。）

```swift:ModalViewController
import Cocoa

class ModalSheetViewController: NSViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do view setup here.
    }
    
    deinit {
        print(#file, ": deinit called.")
    }

    @IBAction
    func doOK(_ sender: NSButton) {
        NSApp.mainWindow?.endSheet(view.window!, returnCode: .OK)
    }
    
    @IBAction
    func doCancel(_ sender: Any) {
        NSApp.mainWindow?.endSheet(view.window!, returnCode: .cancel)
    }
}

```

（説明の順序が逆ですが、）`endSheet`でモーダルを閉じます。


<br>
# StoryboardにNSWindowControllerを追加

- ライブラリ(⇧⌘L)からNS<b>Window</b>ControllerをStoryboardにドラッグドロップします。

- 追加したWindowControllerに任意の`Storyboard ID`を指定します。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/7e75c726-011b-5e43-b59d-4382f13adc83.png)

WindowControllerとViewControllerがペアで追加されます。
左側のペアは、Project新規作成時に用意されているもの。右側のペアがモーダルシート用に追加したもの。

- 追加したViewControllerのクラスとして、前項で作成した`ModalSheetViewController`を指定します。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/f1eb1c5c-0a94-3859-4d11-e21a392bcc37.png)


必要によりラベルやボタン等のコントロールを配置し、outletやactionを接続してください。

<br>
# モーダル表示のコード

下記`doSheetOpen`メソッド内の`beginSheet`がそれ。クロージャー関数でモーダルが閉じられた時の処理を書きます。
StoryboardからWindowControllerのインスタンスを生成するため、前項で設定した`Storyboard ID`を指定します。


```swift:doSheetOpen
import Cocoa

class ViewController: NSViewController {

    @IBOutlet weak var modalResultLabel: NSTextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }

    override var representedObject: Any? {
        didSet {
        // Update the view, if already loaded.
        }
    }

    @IBAction
    func doSheetOpen(_ sender: NSButton) {
        modalResultLabel.stringValue = ""
        let modalSheetWindowController = self.storyboard!.instantiateController(withIdentifier: "ModalSheetWindowController") as! NSWindowController
        view.window?.beginSheet(modalSheetWindowController.window!) {
            switch $0 {
            case .OK: self.modalResultLabel.stringValue = "OK"
                print("OK")
            case .cancel: self.modalResultLabel.stringValue = "Cancel"
                print("Cancel")
            default: break
            }
        }
    }
}
```


<br>
# 動作の様子

![movie.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/34676a7a-6ced-3874-456d-9c6565d8e6b7.gif)

ちなみに、ModalSheetViewControllerのdeinitもちゃんと呼ばれます。

（_macOS 11.6.1 (20G224) / Xcode 13.1 (13A1030d) / Swift 5.5.1 , Target: x86_64-apple-macosx11.0 で動作確認済み_）



<br>
# 参考サイト

https://qiita.com/SolaRayLino/items/a925f22ab9538af0d833

https://github.com/nickkuh/OS-X-Custom-Document-Modal-Window


<br>
APIの使い方等で間違いがあればご指摘ください。
以上です
パケットトレーサーでネットワーク学習1104

・ルータ間にIPアドレスを設定して、ポートを開放する。

（例）
ルータ1
コマンド：Router(config)#interface gigabitEthernet 0/2
コマンド：Router(config-if)#ip address 10.0.0.1 255.255.255.252
コマンド：Router(config-if)#no shutdown

ルータ2
コマンド：Router(config)#interface gigabitEthernet 0/2
コマンド：Router(config-if)#ip address 10.0.0.2 255.255.255.252
コマンド：Router(config-if)#no shutdown


・ルータはルーティングテーブルに対象のIPアドレスが無ければデータを破棄する。


・スタティックルートの設定
(例）
コマンド：Router(config)#ip route 192.168.3.0 255.255.255.0 10.0.0.2


・ルーティングテーブルの確認
（例）
コマンド：Router#show ip route
Codes: L - local, C - connected, S - static,
Gateway of last resort is not set

     192.168.2.0/24 is variably subnetted, 2 subnets, 2 masks
C       192.168.2.0/24 is directly connected, GigabitEthernet0/1
L       192.168.2.254/32 is directly connected, GigabitEthernet0/1
S    192.168.3.0/24 [1/0] via 10.0.0.2
※Sはスタティックルートで設定している印。
Ruby on RailsとReactでECサイト構築

#概要
「[Laravelで同じ実装をドメイン駆動設計(DDD)とMVCで比較してみた(フロントはReact)](https://qiita.com/take-t14/items/71398530e451dcd0c183)」の検証で実装したECサイトを、Ruby on RailsとReactに移植してみました。ただ、Laravel版はMVC、DDD、軽量DDDの3種類で実装していましたが、Ruby on Rails版はMVCのみで実装しています。目的はLaravelとRuby on Railsのアーキテクチャの違いを知ることと、そこで得た知見を今後のソフトウェア開発に活かしたい事だった為です。見た目も機能もそっくりそのままLaravel版と同じです(バリデーションだけ若干簡略化しました)。 Ruby on RailsとReact初学者の為、至らぬ点が多々あるのはご容赦下さい・・・

#ソースコード
https://github.com/take-t14/rails-react-sample

#ミドルウェア
|ミドルウェア|バージョン|
| ---- | ---- |
|PostgreSQL|13.3|
|npm|6.14.12|

#フレームワーク・ライブラリ
|フレームワーク・ライブラリ|バージョン|
| ---- | ---- |
|Ruby|2.4.6p354|
|Rails|5.2.6|
|React|17.0.2|
|material-ui|4.12.3|
|typescript|4.4.4|
|sass|1.38.0|

#Ruby
Laravelで実装していた箇所は全面的にRuby on Railsの形で作り直しが必要でした。ただ、フレームワークのアーキテクチャがLaravelとRailsが似ているので、ほぼ文法の置き換えのみでいけました。

#React
ReactはerbからReactを呼び出す部分だけ工夫が要りましたが、Laravel版で実装していたReactのコンポーネントはほぼそのまま使えました。変更が必要だったのは、Reactへの値受け渡し部分のみでした。LaravelではbladeからReactへ値を連携する際json文字列に変換し、Reactでそのjson文字からオブジェクトへとパースしてました。とこらがRuby on RailsではerbでReactに値を連携する際json文字列にせずに渡せて、Reactでもjson文字列をパースせずともオブジェクトとして受け取れている状態となっていました。内部ではRuby on RailsからReactへ値連携時にjsonへ変換してるとは思いますが、react-railsというgemライブラリのreact_componentという関数を使ったのでそこはブラックボックスで中で何をしているかは分かりません。

#バリデーション
Laravel版ではFormRequestを使ってコントローラーに入る手間でバリデーションをかけていました。これはこれで便利なのですが、Ruby on RailsではActoveRecordにバリデーションチェックを実装する機構が用意されていてそれを用いました。ORMにバリデーションチェックの機能がついているのは非常に合理的だと感じました。理由は、FormRequestだと例えば商品詳細画面とカート追加APIで商品IDをバリデーションチェックする際、両方のリクエスト用に同じバリデーションを実装する必要が出てきます。一方ActiveRecordだと商品IDのバリデーションチェックはProductモデル一カ所に実装すればよく、実装の重複はありません。仕様変更の影響範囲も最小限になります。バリデーションチェックは、DBに近い層でやるActiveRecordのアーキテクチャが優れていると感じました。DDDの場合は商品IDのValueObjectへバリデーションチェックを実装する事で重複は避けられると思います。ただ、参考書籍「[実践ドメイン駆動設計(Object Oriented SELECTION)](https://www.amazon.co.jp/実践ドメイン駆動設計-Object-Oriented-SELECTION-ヴァーン・ヴァーノン/dp/479813161X)」ではValueObjectへバリデーションチェックを実装するのは、ドメインモデルに責務を負わせすぎと言う記載が確かあったと思いますので、この辺は色々な議論はあるかも知れません。

#ファイル数・ステップ数
Laravelと同じ事を実現するのに、Runy on Railsだと実装量が圧倒的に少なくて済みました。Laravel版と比べて2/3位のステップ数におさまりました。言語仕様の違いもありますが、Ruby on Railsではコンポーネントのパスやファイル名が決まっていて、それらを定義する必要が無いのもあります。必要な事は予め用意されていて、徹底的に実装効率を上げる事に配慮されたフレームワークなのだと感じました。その反面、ファイルパスの配備先やファイル名はルールが定められており、独自にカスタムする事は出来ません。また、Active Recordのjoinでは記述形式が独特の書式すぎて、どう書いたら目的のjoinができるのかがわかりにくかったです。言語仕様が実装量を少なくしようとしすぎているのか、はたまた実装スタイルのスマートさを過度に目指しすぎているせいなのか、書式が妙に難解になっている感があります。

|種別|ファイル数|ステップ数|
| ---- | ---- | ---- |
|Laravel版（MVC）|23|725|
|Ruby on Rails版|19|471|

#パフォーマンス
ローカルのKubernetesの環境で実行する限りでは、体感ではキビキビ動いている用に感じました。ところが計測してみると、Laravel版と比較してRuby on Rails版は1.2〜8.2倍時間がかかっていました・・・まぁ7つの処理中5つが200ms未満だったので、許容範囲かなとは思います。ちなみにLaravelはPHP8ですがJITは無効。Rubyは2.4.6なのでJIT未対応バージョンでした。

| 機能 | Laravel(MVC)時間 | Laravel(MVC)メモリ | Rails時間 | Railsメモリ |
| ---- | ---- | ---- | ---- | ---- |
| 商品一覧画面表示 | 118ms | 2750KB | 644ms | 3064KB |
| 商品詳細画面表示 | 20ms | 703KB | 163ms | 40KB |
| カート追加API | 77ms | 646KB | 90ms | 20KB |
| カート画面表示 | 47ms | 610KB | 70ms | 4KB |
| 注文画面表示 | 26ms | 610KB | 112ms | 0KB |
| 注文バリデーションAPI | 102ms | 822KB | 40ms | 440KB |
| 注文確定処理 | 193ms | 1363KB | 1399ms | 8912KB |

#参考書籍
[実践ドメイン駆動設計(Object Oriented SELECTION)](https://www.amazon.co.jp/実践ドメイン駆動設計-Object-Oriented-SELECTION-ヴァーン・ヴァーノン/dp/479813161X)
Googleスライドをフルハイビジョンサイズで画像切り出し

# 概要
YouTube用の動画を作成しているが、説明に使う予定のGoogleスライドを画像で保存したら、フルHDサイズ（1920×1080）ではなかった。
リサイズも面倒なので、PDFでダウンロードしてJPEG変換し、トリミングして画像を作成するようにした。

# 環境

Windows 10 Professional
Python 3.9.2

# 準備

## pdf2imageのインストール

ライブラリ「pdf2image」をインストールする

```python
pip install pdf2image
```
## Popplerのダウンロード

フリーのPDFコマンドラインツールである「Poppler」をインストールする。

[Poppler for windows](https://blog.alivate.com.au/poppler-windows/)

リンク先中央付近の「Latest binary : poppler-0.??.0_x86」をダウンロードする。

# フォルダ構成

フォルダ構成は下記の通り。

PdfToImage/
　├ image_file/
　├ pdf_file/
　│   └ slide.pdf
　├ poppler/
　│　├ local/
　│　├ include/
　│　├ lib/
　│　└ share/
　└ .pyファイル（実行ファイル）

popplerフォルダにダウンロードしたPoppplerのファイルを解凍してそのまま入れる。

# ソースコード

```python
import os
from pathlib import Path
from pdf2image import convert_from_path
import sys
from PIL import Image

# poppler/binを環境変数PATHに追加する
poppler_dir = Path('__file__').parent.absolute() / "poppler/bin"
os.environ["PATH"] += os.pathsep + str(poppler_dir)

# PDFファイルのパス
pdf_path = Path("./pdf_file/slide.pdf")

# PDF -> Image に変換（200dpi）
pages = convert_from_path(str(pdf_path), 200)

# 画像ファイルを１ページずつ保存
image_dir = Path("./image_file")
for i, page in enumerate(pages):
    file_name = pdf_path.stem + "_{:02d}".format(i + 1) + ".jpeg"
    image_path = image_dir / file_name
    # JPEGで保存
    page.save(str(image_path), "JPEG")

#トリミング前の画像の格納先
ORIGINAL_FILE_DIR = "./image_file/"
#トリミング後の画像の格納先
TRIMMED_FILE_DIR = "./cut_file/"

#画像パスと、左上座標、右下座標を指定して、トリミングされたimageオブジェクトを返す。
def trim(path, left, top, right, bottom):
  im = Image.open(path)
  im_trimmed = im.crop((left,top,right,bottom))
  return im_trimmed

if __name__ == '__main__':
  #もしトリミング後の画像の格納先が存在しなければ作る
  if os.path.isdir(TRIMMED_FILE_DIR) == False:
    os.makedirs(TRIMMED_FILE_DIR)

  #トリミングする左上の座標
  left, top = 62, 24
  #トリミングする右上の座標
  right, bottom = 1982, 1104

  #画像ファイル名を取得
  files = os.listdir(ORIGINAL_FILE_DIR)
  #特定の拡張子のファイルだけを採用。実際に加工するファイルの拡張子に合わせる
  #files = [name for name in files if name.split(".")[-1] in ["png","jpg"]]

  for val in files:
    #オリジナル画像へのパス
    path = ORIGINAL_FILE_DIR + val
    #トリミングされたimageオブジェクトを取得
    im_trimmed = trim(path, left, top, right, bottom)
    #トリミング後のディレクトリに保存。ファイル名の頭に"cut_"をつけている
    im_trimmed.save(TRIMMED_FILE_DIR+"cut_"+val, quality=95) #qualityは95より大きい値は推奨されていないらしい
```

実行すると、「cut_file」というフォルダが作られ、その中に"cut_slide_**.jpeg"というトリミングした画像が格納される。

#参考
PDFからJPEG画像の取得
[PythonでPDFを画像ファイル（JPEG、PNG）に変換する方法](https://gammasoft.jp/blog/convert-pdf-to-image-by-python/)
JPEGのトリミング
[画像を一括でトリミング【python】【Pillow】](https://qiita.com/shimajiroxyz/items/2a8487fc37604e9b5464)
`name ‘__file__’ is not defined`の解決
[Python NameError: name ‘__file__’ is not definedのエラー](https://www.souichi.club/python/file-is-not-defined/)
記事を書くときの参考
[ディレクトリ構成図を書くときに便利な記号](https://qiita.com/paty-fakename/items/c82ed27b4070feeceff6)
[サーバレス] 記念日を７日前に予告してくれるbotを作った

# 記念日を事前に知りたい

こんにちは。mogyaです。最近の趣味は、インフルエンサーの女の子のマネをして映え写真を撮ってインスタにあげることです。フォロワーさんも順調に増えているよ。

![Artboard 1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30743/7519156f-3c93-4f5c-39e3-975315f2b581.jpeg)

こういう趣味とか、コスプレイヤーなど、自撮りした写真をSNSに上げたい人にとって、記念日というのはわりと重要な意味を持ちます。メガネの日には眼鏡をかけた写真を上げたり、ミニスカートの日にはミニスカートの写真を上げたり、その日に合わせた写真というのは、そうでない写真よりもフォロワーさんの反応がいいのです。

世の中にはそういう記念日を教えてくれるBotというのがたくさんあるのですけど、「今日はメガネの日です」と言われても、かわいい写真を取るには相応の準備が必要なので、当日言われても遅いわ！ということになりがちです。遅くとも一週間前には教えていただきたい！

ということで、最近メイクとか洋服に夢中になって失われつつあるエンジニア能力のリハビリも兼ねて、TwitterBotを作りました。

# データを集めよう

テレビとかネットで記念日を話題にする場合、だいたいは[日本記念日協会](https://www.kinenbi.gr.jp/) のデータをもとにしていることが多いです。ただここはぶっちゃけ記念日を登録しておくことが商売なので、データのダウンロードは有償で、勝手にぶっこ抜くと怒られそうです。
順当にフォロワーさんが増えてきたら考えないでもないのですけど、まずはMVPということで、Wikipediaからお借りしてきました。

[日本の記念日一覧 - Wikipedia](https://ja.wikipedia.org/wiki/%E6%97%A5%E6%9C%AC%E3%81%AE%E8%A8%98%E5%BF%B5%E6%97%A5%E4%B8%80%E8%A6%A7)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30743/00e7b0a7-5728-63f5-bf76-05ad3028a215.png)

適当に計算式を入れると、記念日と、その７日前の日付と、ツイートすべきテキストの集合を定義することが出来ました。立冬の日とかは、手作業で日付に直していますw


# ツイートしよう

Twitter APIへのアクセスは、みんなご存知[TwitterWebService.gs](https://gist.github.com/M-Igashi/750ab08718687d11bff6322b8d6f5d90)を使いました。OAuth1が古いから新しいのに置き換えないといけないのとか、みんな知ってるよね。

地味にハマったのが、「今日ツイートすべきデータを取ってくる」処理です。ループ回してその日の日付のデータを取ってくるだけなのですが、ゆるふわ頭脳だとそういうのを書くのも困難です。GASのデバッガって使い勝手悪いから、動かないときの原因を突き止めるのも大変だし。

スプレッドシートの内容をAPIにしてくれる[sssapi](https://sssapi.app/) をつかって自分をAPI化して、そのAPIからとってきたデータをツイートする、という仕組みにしたのですけど、そこまで書いたあたりでようやく技術脳が目を覚ましたのか、「ループで回して今日の日付だったらそれをツイートする」だけだよね、ということに気づいたので、SSSAPIは結局使わないことになってしまいました。でもSSSAPI自体は便利なのでまたなんかの機会に使ってみたいですね。

# 出来た

ということで出来上がったのが、[７日後はなんの日？bot] (https://twitter.com/nannohi_7) です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30743/cf6198ff-039d-30d7-9d7b-96dc5ed6ec28.png)

ちょうどいいタイミングでネイルの日が予告されています。よーし、今週末はめっちゃかっこいいネイルを撮って準備するぞ、という計画ができる余裕、嬉しいですよね。

スプレッドシート単体で完結しているので運用費用はかからないし、日付とツイート内容があれば全然別のbotにも転用できそう。ソースコードはGistにあげておいたので、興味があればご覧ください
https://gist.github.com/mogya/c3e2b4654d4898c7a06d300eb6443064
Wineでの日本語の文字化けを修正する方法

## 概要

以前Crackmeと呼ばれるリバースエンジニアリングの問題を解いていた時に、WindowsのバイナリファイルをLinuxで動かしたい状況がありました。
そのため、Wineを使ってWindowsのバイナリを走らせたのですが、日本語が文字化けしてしまっていました。

そこで、今回は僕が成功した修正方法をお伝えしたいと思います。
この方法で解決するとは限らないのでご了承ください。あくまで僕の場合は成功したという話です。

## 環境

僕が使用した環境を参考までにお伝えします。
あまり重要ではないですが、一応載せておきます。

OS：Kali Linux x64
仮想化ソフト：Virtual Box
ホストOS：Windows10

## 修正方法

wineコマンドの前に"LC_ALL=ja_JP.utf8"を付けるだけです。

```
LC_ALL=ja_JP.utf8 wine test.exe
```

ちなみにKali Linuxのキーボードを日本語に対応させるために、僕はこれらのコマンドを事前に入力していました。
皆さんも実行しておいた方がいいと思います。（多分）

```
sudo apt-get install -y task-japanese task-japanese-desktop
sudo dpkg-reconfigure locales
sudo update-locale LANG=ja_JP.UTF-8
```

## 最後に

ググってみると、この方法で上手くいかなかった人もちらほらいるらしいです。
どうやら他にもっとメジャーな方法もある様ですが、僕のケースも残しておこうかなという感じで書きました。

この記事が皆さんのお役に立てれば嬉しいです。最後まで読んでくださってありがとうございました。

質問がある方は是非コメントしてください😃
【css】波打つラインを「表現」する

よく見る波打つようなエフェクト。
SVGアニメーションで再現するんじゃなくて、cssのみでそれっぽく見せる。

<p class="codepen" data-height="500" data-default-tab="html,result" data-slug-hash="BadoZOj" data-user="masayuki-abe" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/masayuki-abe/pen/BadoZOj">
  波打つように見える回転する円</a> by masayuki abe (<a href="https://codepen.io/masayuki-abe">@masayuki-abe</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

仕組みとしては、`border-dadius`で作った楕円を回転させることで波打っているように見せる、となる。
一つの楕円を回転させるだけでもそれっぽく見せることができるけど、
2つの楕円を重ねて、`mix-blend-mode: multiply;`で色を重ねてあげるとちょっと面白くなる。
背景色を指定せず、`border`だけで表現しても良いと思う。

ポイントは、`transform-origin`で回転の中心点をアニメーションで少しずらしてあげること。
これより、波打っているように見せることができる。

SVGでゴリゴリっとやるところまでは行かないけれど、メインビジュアルとかでなんか一工夫ほしいときには
使えるんじゃないかなーと思ってる。水系のサイトとか、イノベーションとかって謳ってるサイトとか。

IE11は非検証だけど、動くんじゃないかなー、と勝手に思ってる。
`mix-blend-mode`は使えないけれど、そこは`opacity`でそれっぽく。
Windows11の32bit版(半分嘘ｗ)

皆さんご存知の通り、Windows11に32bit版はありません。ただし、それはフルサイズの場合です。
↓の通り、Win11ベースのWindowsPEには32bit版があるのです(WindowsADKから作成)。ブート方法もBIOSブート可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547444/1a7a2313-2096-8044-fe08-6cdee065a5aa.png)

しかしまぁ...WindowsPEって主にWindowsインストール関連のためにあるのですよね。本体のOSがないのになぜPEがあるのかが謎です。やはりMS内部にはWin11の32bit版が存在しているということなんでしょうか？

↓おまけ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547444/9f9bea04-e2c0-d91d-9b93-ebaf5414793c.png)
変数名に変数をいれる

## 開発環境
`ruby 2.6.5`
`Ruby on Rails 5.2.5`

## 本題

```
    @ranking1 = Ranking.find_by(user_id: ranking_user_id, rank: 1)
    @ranking2 = Ranking.find_by(user_id: ranking_user_id, rank: 2)
    @ranking3 = Ranking.find_by(user_id: ranking_user_id, rank: 3)
```

こんなコードがあり、リファクタリングしたかった

まずは普通に

```
    3.times do |n|
      @ranking "#{n+1}" = Ranking.find_by(user_id: ranking_user_id, rank: n + 1)
    end
```
とかしてみる
しかしシンタックスエラー

書き方が悪いのかなっておもっていろいろやってみたけど
どうやら変数名に変数はいれられないみたい

___

https://qiita.com/fuma_0222/items/e9623a277780f5de2041

この記事を参考にさせて頂いた。

どうやら変数名に変数をいれるメソッドがあるらしい

参考にしながら

```
 3.times do |n|
    ranking = Ranking.find_by(user_id: ranking_user_id, rank: n + 1)
    instance_variable_set("@ranking#{n+1}", ranking )
 end
```

でいけた
ぼっち演算子をつかって思いがけないエラー回避する

## 開発環境
`ruby 2.6.5`
`Ruby on Rails 5.2.5`

## 本題
スクレイピングしてきたデータを使いやすいようにする

[![Image from Gyazo](https://i.gyazo.com/353482254a087cef277dc66b6caab0ea.png)](https://gyazo.com/353482254a087cef277dc66b6caab0ea)

こんなふうに `origin_shrine` のデータが入っていてこのままだと `chatkick` で使えない

やりたいことは（ の前だけを取り出したい
今回のパターンだと使いたいのは熊野三山

そのために使うのは前方参照

```
a = chart_shinto.origin_shrine.match(/（/).pre_match 
```

変数に `match` メソッドをつかって（ を正規表現で探し当てる

そして `pre_match` メソッドをつかうことでその前の値を返す

実際に見てみると

[![Image from Gyazo](https://i.gyazo.com/1cacfcbd30fd141f2c7ac611f26f3b24.png)](https://gyazo.com/1cacfcbd30fd141f2c7ac611f26f3b24)

ちゃんととれてる

で、ここからが本題

このままだと （　がないときにエラーが発生する
なぜなら `nil` に対して `pre_match` メソッドを実行する形になるから

実際全てのデータを確認して（ をつけるようにしたけど不安があった。

なのでぼっち演算子をつかって `match` の返り値が `nil` だったら `pre_match` を実行しないようにする

コードは

```
chart_shinto.origin_shrine.match(/（/)&.pre_match
```

これなら（ がなくてもエラーが起きない
整数計画ソルバーGurobiのインストール方法【学生無料】

# 初めに
Gurobiは商用であれば何百万も払わなければいけない最強数理最適化ソルバーですが、大学の研究、教育目的であればフル機能を無償で使用できます。
Googlecolabなどでは動きませんので、ローカルにインストールしてご使用ください。
Googlecolabで最適化したい場合はpulpやgurobiと同じ文法で使えるmypulpをご利用ください。

# Gurobiのインストール
## pipでインストールする場合
anacondaを使わずにpyenvやpoetryで環境構築をしている場合は以下のコマンドでインストール可能です。

```terminal
$ python -m pip install gurobipy
```

## condaを使用してインストールする
anacondaを使用している場合はこちら。anaconda pronptを使用してもいいかも。

```terminal
$ conda config --add channels http://conda.anaconda.org/gurobi
$ conda install gurobi
```
下記参考まで
https://www.gurobi.com/get-anaconda/

# アカウント登録
https://pages.gurobi.com/registration

1.ここから登録してください。
    - account typeは**Academic**を選択
    - Company/University は自分の大学名を入力してください。
    - 大学のメールアドレス(ac.jp)を使って登録してください。
2.登録したメールアドレスにメールが届きます。それに従ってパスワードを設定してください.

3.ログイン後、[GurobiのHP](https://www.gurobi.com/)から`Download&Licenses`->`Academic License`をクリック。
![スクリーンショット 2021-10-29 13.32.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/571279/4c4bf4a8-836b-69b8-5088-72f904a9d2e8.png)

4.Free Academic License のページが表示されるので, Request Licenseしてください。

****
以前はここからの操作は大学のネットワークに接続してなければ行えませんでした。が、今はその必要はないです。
学校によっては不可能な可能性もなくはないですが、その場合は大学のネットワーク下で行なってください。VPNでも大丈夫です。
*****

5.以下のようにライセンスが発行されます。赤丸内のの`grbgetkey xxxxx`をターミナル、もしくはコマンドプロンプトで実行してください。ライセンスファイルが生成され、登録が完了します。

![b417b124d466631c85cc6ada1bda1369.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/571279/131c236b-08de-3a28-631d-fa40bad7b9be.png)


# ２回目以降
ライセンスファイルはもちろん期限があるので、一定期間が過ぎたら、上記の３~5をもう一度行なってください。新しいライセンスファイルが発行されるはずです。
`grbgetkey xxxxxxxxxxx`を実行し、Y/Nを聞かれるのでYを入力してください。

# 使用方法

```Python
from gurobipy import *
```
でエラーが出なければ問題ありません。

文法は公式ドキュメントをご参考に
https://www.gurobi.com/documentation/
docker-compose public の内容が反映されないときに疑うべきこと

## 開発環境

`Docker version 20.10.7`
`docker-compose version 1.29.2`

## 本題
`EC2`上にて `docker-compose` をつかってイメージをビルドした際に
`public` の内容が反映されなかった。

`docker-compose build --no-cache` ってしてもだめ

試しに `docker-compose run app exec bash` でコンテナにはいって調べると
やはり反映されていない

ただ、今回は画像を1GBくらい `public` においたんだけど
`docker image ls` ってするときちんと1GB 分イメージ容量が増えている

なんだ
___

https://ysko909.github.io/posts/delete-volume-if-can-not-update-container/

`volume` の書き方によってはゴミがのこってしまうみたい。
今回はそれで反映されなかった。

`Docker` むずかしい
画像に透過処理をかける

##2021/12/16追記
こちらで十分でした。すごい。

https://www.remove.bg/ja




##趣旨
画像を使うときに背景を消したい（透過処理）ことがよくあるのでやり方をまとめました。


##使用するもの
ペイント3D（ペイントの後継なのWindowsなら既に導入されているはずです）

https://www.microsoft.com/ja-jp/p/%E3%83%9A%E3%82%A4%E3%83%B3%E3%83%88-3d/9nblggh5fv99?activetab=pivot:overviewtab




#実際にやってみる
こちらの画像から背景を除去してナオトインティライミだけ切り出します
![naoto.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2143015/b681ade1-856a-390a-73dc-625854f7b1bc.jpeg)

####１．ペイント3Dを起動して、処理したい画像ファイルを開き、マジック選択を選ぶ。
![キャプチャ1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2143015/abff9769-58e4-860d-20c0-bec00f08f123.png)


####２．右の案内に従って進むと以下のような画面にたどり着く。
暗転している箇所は除去される部分。機械的に処理されたものなので、「追加」「削除」を選択して過不足を補正していく。色が近いとうまく除去されないので、そこは手で頑張るしかない。
**残したい／消したい箇所をダブルクリックするとその周辺を機械処理してくれる**ので活用するとよい。
![キャプチャ2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2143015/478fc558-9ed5-475c-ecbc-31c6a6891767.png)

####３．補正が完了したら完了ボタンを押す。
![キャプチャ3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2143015/dda22093-1f1d-3d8d-7693-99664f5bd896.png)

####４．抜き出す画像をドラッグすると残したい部分だけがオブジェクトとしてはがれるのでコピーして、新しいファイルを作成しペーストする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2143015/1fad8571-8b87-b814-2008-5f7a336c04af.png)

####５．新しいファイルにペーストしたら、キャンバスを選択して透明なキャンバスをオンにして保存する。
![キャプチャ4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2143015/b5a5d195-14cf-9b6a-277e-548d15079961.png)
↓こうなる
![キャプチャ5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2143015/c910ad9c-bf0a-19e4-e6a6-e6518b8df91f.png)
↓透過しているかいまいちわからないので、以下のサイトで確かめる。
背景が市松模様＝透過

https://www.photopea.com/

↓なってた
![キャプチャ6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2143015/78086ef0-e5b4-ef7b-1bd3-0454b6752d3c.png)


####注意
透過処理後に画像を編集したりすると透過が解除されるので注意が必要
拡大・縮小のためにペイントで編集したら透過処理が解除された
拡大・縮小はフォトからやろう